{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "58b1f0a7-d62e-4f71-ba01-b8f0beaeeb83",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Crear un complemento transpilador\"\n",
        "description: \"Cómo crear un complemento transpilador Qiskit para compartir tu código de transpilación con la comunidad Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"create-a-transpiler-plugin\" />\n",
        "\n",
        "# Crear un complemento transpilador\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5ec7b7a4-5318-4422-ab3d-c88cee551eaa",
      "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": "a7f87a76-b7a1-4dbb-ad45-55ff63c4665b",
      "metadata": {},
      "source": [
        "Crear un [plugin de transpilador](transpiler-plugins) es una buena forma de compartir tu código de transpilación con toda la comunidad Qiskit, permitiendo que otros usuarios se beneficien de la funcionalidad que has desarrollado. Gracias por tu interés en contribuir a la comunidad Qiskit\n",
        "\n",
        "Antes de crear un plugin de transpilador, tienes que decidir qué tipo de plugin es el adecuado para tu situación. Existen tres tipos de plugins transpiladores:\n",
        "\n",
        "* [**Transpiler stage plugin**](/docs/api/qiskit/transpiler_plugins). Seleccione esta opción si está definiendo un gestor de pases que pueda sustituir a una de las [6 etapas](transpiler-stages) de un gestor de pases por etapas preestablecido.\n",
        "* [**Plugin de síntesis unitaria**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin). Elija esta opción si su código de transpilación toma como entrada una matriz unitaria (representada como una matriz Numpy) y da como salida una descripción de un circuito cuántico que implemente esa matriz unitaria.\n",
        "* [**Plugin de síntesis de alto nivel**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin). Elija esta opción si su código de transpilación toma como entrada un \"objeto de alto nivel\", como un operador Clifford o una función lineal, y da como salida una descripción de un circuito cuántico que implementa ese objeto de alto nivel. Los objetos de alto nivel están representados por subclases de la clase [Operación](/docs/api/qiskit/qiskit.circuit.Operation).\n",
        "\n",
        "Una vez que hayas determinado qué tipo de plugin crear, sigue estos pasos para crear el plugin:\n",
        "\n",
        "1. Crear una subclase de la clase plugin abstracta apropiada:\n",
        "   * [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin) para un plugin de etapa de transpilador,\n",
        "   * [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) para un plugin de síntesis unitaria, y\n",
        "   * [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) para un plugin de síntesis de alto nivel.\n",
        "2. Exponga la clase como un [punto de entrada setuptools](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) en los metadatos del paquete, normalmente editando el archivo `pyproject.toml`, `setup.cfg`, o `setup.py` para su paquete Python.\n",
        "\n",
        "No hay límite en el número de plugins que puede definir un mismo paquete, pero cada plugin debe tener un nombre único. El propio SDK de Qiskit incluye una serie de plugins, cuyos nombres también están reservados. Los nombres reservados son:\n",
        "\n",
        "* Plugins de etapa del transpilador: Consulte [esta tabla](/docs/api/qiskit/transpiler_plugins#plugin-stages).\n",
        "* Plugins de síntesis unitaria: `default`, `aqc`, `sk`\n",
        "* Plugins de síntesis de alto nivel:\n",
        "\n",
        "| Clase de operación                                                                         | Nombre de operación | nombres reservados                                |\n",
        "| ------------------------------------------------------------------------------------------ | ------------------- | ------------------------------------------------- |\n",
        "| [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford#clifford)                         | `clifford`          | `default`, `ag`, `bm`, `greedy`, `layers`, `lnn`  |\n",
        "| [LinearFunction](/docs/api/qiskit/qiskit.circuit.library.LinearFunction#linearfunction)    | `linear_function`   | `default`, `kms`, `pmh`                           |\n",
        "| [PermutationGate](/docs/api/qiskit/qiskit.circuit.library.PermutationGate#permutationgate) | `permutation`       | `default`, `kms`, `basic`, `acg`, `token_swapper` |\n",
        "\n",
        "En las siguientes secciones, mostramos ejemplos de estos pasos para los distintos tipos de plugins. En estos ejemplos, suponemos que estamos creando un paquete Python llamado `my_qiskit_plugin`. Para obtener información sobre la creación de paquetes Python, puede consultar [este tutorial](https://packaging.python.org/en/latest/tutorials/packaging-projects/) del sitio web Python.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4519c0dc-2bcd-48f4-8522-435b72efdb40",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-transpiler-stage-plugin\" />\n",
        "\n",
        "## Ejemplo: Crear un complemento de etapa transpilador\n",
        "\n",
        "En este ejemplo, creamos un plugin de etapa de transpilación para la etapa `layout` (ver [Etapas de transpilación](transpiler-stages) para una descripción de las 6 etapas del pipeline de transpilación incorporado en Qiskit).\n",
        "Nuestro plugin simplemente ejecuta [VF2Layout](/docs/api/qiskit/qiskit.transpiler.passes.VF2Layout) durante un número de pruebas que depende del nivel de optimización solicitado.\n",
        "\n",
        "En primer lugar, creamos una subclase de [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin). Hay un método que necesitamos implementar, llamado [`pass_manager`](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin#pass_manager). Este método toma como entrada un [PassManagerConfig](/docs/api/qiskit/qiskit.transpiler.PassManagerConfig) y devuelve el gestor de pases que estamos definiendo. El objeto PassManagerConfig almacena información sobre el backend de destino, como su mapa de acoplamiento y sus puertas base.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "f90299d9-5026-424c-b528-6d0defdddb54",
      "metadata": {},
      "outputs": [],
      "source": [
        "# This import is needed for python versions prior to 3.10\n",
        "from __future__ import annotations\n",
        "\n",
        "from qiskit.transpiler import PassManager\n",
        "from qiskit.transpiler.passes import VF2Layout\n",
        "from qiskit.transpiler.passmanager_config import PassManagerConfig\n",
        "from qiskit.transpiler.preset_passmanagers import common\n",
        "from qiskit.transpiler.preset_passmanagers.plugin import (\n",
        "    PassManagerStagePlugin,\n",
        ")\n",
        "\n",
        "\n",
        "class MyLayoutPlugin(PassManagerStagePlugin):\n",
        "    def pass_manager(\n",
        "        self,\n",
        "        pass_manager_config: PassManagerConfig,\n",
        "        optimization_level: int | None = None,\n",
        "    ) -> PassManager:\n",
        "        layout_pm = PassManager(\n",
        "            [\n",
        "                VF2Layout(\n",
        "                    coupling_map=pass_manager_config.coupling_map,\n",
        "                    properties=pass_manager_config.backend_properties,\n",
        "                    max_trials=optimization_level * 10 + 1,\n",
        "                    target=pass_manager_config.target,\n",
        "                )\n",
        "            ]\n",
        "        )\n",
        "        layout_pm += common.generate_embed_passmanager(\n",
        "            pass_manager_config.coupling_map\n",
        "        )\n",
        "        return layout_pm"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d7666879-14bc-479c-a91b-56a800897073",
      "metadata": {},
      "source": [
        "Ahora, exponemos el plugin añadiendo un punto de entrada en los metadatos de nuestro paquete Python.\n",
        "Aquí, asumimos que la clase que definimos está expuesta en un módulo llamado `my_qiskit_plugin`, por ejemplo al ser importada en el archivo `__init__.py` del módulo `my_qiskit_plugin` .\n",
        "Editamos el archivo `pyproject.toml`, `setup.cfg`, o `setup.py` de nuestro paquete (dependiendo del tipo de archivo que haya elegido para almacenar los metadatos de su proyecto Python ):\n",
        "\n",
        "<Tabs>\n",
        "  <TabItem value=\"package-table-toml\" label=\"pyproject.toml\" default>\n",
        "    ```toml\n",
        "    [project.entry-points.\"qiskit.transpiler.layout\"]\n",
        "    \"my_layout\" = \"my_qiskit_plugin:MyLayoutPlugin\"\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-cfg\" label=\"setup.cfg\">\n",
        "    ```ini\n",
        "    [options.entry_points]\n",
        "    qiskit.transpiler.layout =\n",
        "        my_layout = my_qiskit_plugin:MyLayoutPlugin\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-py\" label=\"setup.py\">\n",
        "    ```python\n",
        "    from setuptools import setup\n",
        "\n",
        "    setup(\n",
        "        # ...,\n",
        "        entry_points={\n",
        "            'qiskit.transpiler.layout': [\n",
        "                'my_layout = my_qiskit_plugin:MyLayoutPlugin',\n",
        "            ]\n",
        "        }\n",
        "    )\n",
        "    ```\n",
        "  </TabItem>\n",
        "</Tabs>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5c5edd30",
      "metadata": {},
      "source": [
        "Consulte la [tabla de etapas del plugin de](/docs/api/qiskit/transpiler_plugins#stage-table) transpilador para conocer los puntos de entrada y las expectativas de cada etapa del transpilador.\n",
        "\n",
        "Para comprobar que tu plugin es detectado correctamente por Qiskit, instala tu paquete de plugins y sigue las instrucciones en [Transpiler plugins](transpiler-plugins#list-available-transpiler-stage-plugins) para listar los plugins instalados, y asegúrate de que tu plugin aparece en la lista:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "04b07ec3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['default', 'dense', 'sabre', 'trivial']"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler.preset_passmanagers.plugin import list_stage_plugins\n",
        "\n",
        "list_stage_plugins(\"layout\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d62c4edb",
      "metadata": {},
      "source": [
        "Si nuestro plugin de ejemplo estuviera instalado, entonces el nombre `my_layout` aparecería en esta lista.\n",
        "\n",
        "Si desea utilizar una etapa de transpilador incorporada como punto de partida para su plugin de etapa de transpilador, puede obtener el gestor de pases para una etapa de transpilador incorporada utilizando [PassManagerStagePluginManager](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePluginManager#passmanagerstagepluginmanager). La siguiente celda de código muestra cómo hacerlo para obtener la etapa de optimización incorporada para el nivel de optimización 3.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "f4d578d6",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler.preset_passmanagers.plugin import (\n",
        "    PassManagerStagePluginManager,\n",
        ")\n",
        "\n",
        "# Initialize the plugin manager\n",
        "plugin_manager = PassManagerStagePluginManager()\n",
        "\n",
        "# Here we create a pass manager config to use as an example.\n",
        "# Instead, you should use the pass manager config that you already received as input\n",
        "# to the pass_manager method of your PassManagerStagePlugin.\n",
        "pass_manager_config = PassManagerConfig()\n",
        "\n",
        "# Obtain the desired built-in transpiler stage\n",
        "optimization = plugin_manager.get_passmanager_stage(\n",
        "    \"optimization\", \"default\", pass_manager_config, optimization_level=3\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fe3a1a6c-5aa2-4f00-9bdd-45598717be1d",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-unitary-synthesis-plugin\" />\n",
        "\n",
        "## Ejemplo: Crear un complemento de síntesis unitaria\n",
        "\n",
        "En este ejemplo, crearemos un plugin de síntesis unitaria que simplemente utiliza el pase de transpilación integrado [UnitarySynthesis](/docs/api/qiskit/qiskit.transpiler.passes.UnitarySynthesis#unitarysynthesis) para sintetizar una puerta. Por supuesto, tu propio plugin hará algo más interesante que eso.\n",
        "\n",
        "La clase [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) define la interfaz y el contrato para los plugins de síntesis unitaria unitaria. El método principal es [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run), que toma como entrada una matriz Numpy que almacena una matriz unitaria y devuelve un [DAGCircuit](/docs/api/qiskit/qiskit.dagcircuit.DAGCircuit) que representa el circuito sintetizado a partir de esa matriz unitaria.\n",
        "Además del método `run` , hay una serie de métodos de propiedad que deben definirse.\n",
        "Consulte [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) para obtener documentación sobre todas las propiedades necesarias.\n",
        "\n",
        "Vamos a crear nuestra subclase UnitarySynthesisPlugin :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "6bc1011c-b15d-4210-973b-d9d530ece880",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from qiskit.circuit import QuantumCircuit, QuantumRegister\n",
        "from qiskit.converters import circuit_to_dag\n",
        "from qiskit.dagcircuit.dagcircuit import DAGCircuit\n",
        "from qiskit.quantum_info import Operator\n",
        "from qiskit.transpiler.passes import UnitarySynthesis\n",
        "from qiskit.transpiler.passes.synthesis.plugin import UnitarySynthesisPlugin\n",
        "\n",
        "\n",
        "class MyUnitarySynthesisPlugin(UnitarySynthesisPlugin):\n",
        "    @property\n",
        "    def supports_basis_gates(self):\n",
        "        # Returns True if the plugin can target a list of basis gates\n",
        "        return True\n",
        "\n",
        "    @property\n",
        "    def supports_coupling_map(self):\n",
        "        # Returns True if the plugin can synthesize for a given coupling map\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_natural_direction(self):\n",
        "        # Returns True if the plugin supports a toggle for considering\n",
        "        # directionality of 2-qubit gates\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_pulse_optimize(self):\n",
        "        # Returns True if the plugin can optimize pulses during synthesis\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_gate_lengths(self):\n",
        "        # Returns True if the plugin can accept information about gate lengths\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_gate_errors(self):\n",
        "        # Returns True if the plugin can accept information about gate errors\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_gate_lengths_by_qubit(self):\n",
        "        # Returns True if the plugin can accept information about gate lengths\n",
        "        # (The format of the input differs from supports_gate_lengths)\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_gate_errors_by_qubit(self):\n",
        "        # Returns True if the plugin can accept information about gate errors\n",
        "        # (The format of the input differs from supports_gate_errors)\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def min_qubits(self):\n",
        "        # Returns the minimum number of qubits the plugin supports\n",
        "        return None\n",
        "\n",
        "    @property\n",
        "    def max_qubits(self):\n",
        "        # Returns the maximum number of qubits the plugin supports\n",
        "        return None\n",
        "\n",
        "    @property\n",
        "    def supported_bases(self):\n",
        "        # Returns a dictionary of supported bases for synthesis\n",
        "        return None\n",
        "\n",
        "    def run(self, unitary: np.ndarray, **options) -> DAGCircuit:\n",
        "        basis_gates = options[\"basis_gates\"]\n",
        "        synth_pass = UnitarySynthesis(basis_gates, min_qubits=3)\n",
        "        qubits = QuantumRegister(3)\n",
        "        circuit = QuantumCircuit(qubits)\n",
        "        circuit.append(Operator(unitary).to_instruction(), qubits)\n",
        "        dag_circuit = synth_pass.run(circuit_to_dag(circuit))\n",
        "        return dag_circuit"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6daebf1b-aa38-44a8-bf62-eea96838e95f",
      "metadata": {},
      "source": [
        "Si considera que las entradas disponibles para el [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run) son insuficientes para sus fines, [abra una incidencia](https://github.com/Qiskit/qiskit/issues/new/choose) explicando sus necesidades. Los cambios en la interfaz de los plugins, como la adición de entradas opcionales adicionales, se realizarán de forma compatible con versiones anteriores para que no requieran cambios en los plugins existentes.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Nota\">\n",
        "  Todos los métodos prefijados con `supports_` están reservados en una clase derivada de `UnitarySynthesisPlugin` como parte de la interfaz. No debe definir ningún método personalizado `supports_*` en una subclase que no esté definido en la clase abstracta.\n",
        "</Admonition>\n",
        "\n",
        "Ahora, exponemos el plugin añadiendo un punto de entrada en los metadatos de nuestro paquete Python.\n",
        "Aquí, asumimos que la clase que definimos está expuesta en un módulo llamado `my_qiskit_plugin`, por ejemplo al ser importada en el archivo `__init__.py` del módulo `my_qiskit_plugin` .\n",
        "Editamos el archivo `pyproject.toml`, `setup.cfg`, o `setup.py` de nuestro paquete:\n",
        "\n",
        "<Tabs>\n",
        "  <TabItem value=\"package-table-toml\" label=\"pyproject.toml\" default>\n",
        "    ```toml\n",
        "    [project.entry-points.\"qiskit.unitary_synthesis\"]\n",
        "    \"my_unitary_synthesis\" = \"my_qiskit_plugin:MyUnitarySynthesisPlugin\"\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-cfg\" label=\"setup.cfg\">\n",
        "    ```ini\n",
        "    [options.entry_points]\n",
        "    qiskit.unitary_synthesis =\n",
        "        my_unitary_synthesis = my_qiskit_plugin:MyUnitarySynthesisPlugin\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-py\" label=\"setup.py\">\n",
        "    ```python\n",
        "    from setuptools import setup\n",
        "\n",
        "    setup(\n",
        "        # ...,\n",
        "        entry_points={\n",
        "            'qiskit.unitary_synthesis': [\n",
        "                'my_unitary_synthesis = my_qiskit_plugin:MyUnitarySynthesisPlugin',\n",
        "            ]\n",
        "        }\n",
        "    )\n",
        "    ```\n",
        "  </TabItem>\n",
        "</Tabs>\n",
        "\n",
        "Al igual que antes, si su proyecto utiliza `setup.cfg` o `setup.py` en lugar de `pyproject.toml`, consulte la [documentación de setuptools](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) para saber cómo adaptar estas líneas a su situación.\n",
        "\n",
        "Para comprobar que tu plugin es detectado correctamente por Qiskit, instala tu paquete de plugins y sigue las instrucciones en [Transpiler plugins](transpiler-plugins#list-available-unitary-synthesis-plugins) para listar los plugins instalados, y asegúrate de que tu plugin aparece en la lista:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "31bfaf30",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['aqc', 'clifford', 'default', 'gridsynth', 'sk']"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler.passes.synthesis import unitary_synthesis_plugin_names\n",
        "\n",
        "unitary_synthesis_plugin_names()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4faf2d51",
      "metadata": {},
      "source": [
        "Si nuestro plugin de ejemplo estuviera instalado, entonces el nombre `my_unitary_synthesis` aparecería en esta lista.\n",
        "\n",
        "Para dar cabida a los plugins de síntesis unitaria que exponen múltiples opciones, la interfaz de plugins tiene una opción para que los usuarios proporcionen una forma libre diccionario de configuración. Esto se pasará al método `run` mediante el argumento de la palabra clave `options` . Si tu plugin tiene estas opciones de configuración, deberías documentarlas claramente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "651c863d-41d9-41f4-a133-b392dae2f363",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-high-level-synthesis-plugin\" />\n",
        "\n",
        "## Ejemplo: Crear un complemento de síntesis de alto nivel\n",
        "\n",
        "En este ejemplo, crearemos un plugin de síntesis de alto nivel que simplemente utiliza la función incorporada [synth\\_clifford\\_bm](/docs/api/qiskit/synthesis#synth_clifford_bm) para sintetizar un operador Clifford.\n",
        "\n",
        "La clase [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) define la interfaz y el contrato para los plugins de síntesis de alto nivel. El método principal es [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin#run).\n",
        "El argumento posicional `high_level_object` es una [Operación](/docs/api/qiskit/qiskit.circuit.Operation) que representa el objeto de \"alto nivel\" a sintetizar. Por ejemplo, podría ser un [LinearFunction](/docs/api/qiskit/qiskit.circuit.library.LinearFunction) o un [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford).\n",
        "Existen los siguientes argumentos de palabra clave:\n",
        "\n",
        "* `target` especifica el backend de destino, lo que permite al plugin acceder a toda la información específica del objetivo, como el mapa de acoplamiento, el conjunto de puertas soportadas, etc\n",
        "* `coupling_map` sólo especifica el mapa de acoplamiento, y sólo se utiliza cuando no se especifica `target` .\n",
        "* `qubits` especifica la lista de qubits sobre la que se define el objeto de alto nivel, en caso de que la síntesis se realice sobre el circuito físico.\n",
        "  Un valor de `None` indica que aún no se ha elegido la disposición y que aún no se han determinado los qubits físicos del mapa de destino o de acoplamiento sobre los que opera esta operación.\n",
        "* `options`un diccionario de configuración libre para las opciones específicas del plugin. Si su plugin tiene estas opciones de configuración debe documentarlas claramente.\n",
        "\n",
        "El método `run` devuelve un [QuantumCircuit](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) que representa el circuito sintetizado a partir de ese objeto de alto nivel.\n",
        "También se permite devolver `None`, indicando que el plugin no puede sintetizar el objeto de alto nivel dado.\n",
        "La síntesis real de los objetos de alto nivel es realizada por el módulo [HighLevelSynthesis](/docs/api/qiskit/qiskit.transpiler.passes.HighLevelSynthesis) transpilador.\n",
        "\n",
        "Además del método `run` , hay una serie de métodos de propiedad que deben definirse.\n",
        "Consulte [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) para obtener documentación sobre todas las propiedades necesarias.\n",
        "\n",
        "Definamos nuestra subclase HighLevelSynthesisPlugin :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "3c0e59d4-85b0-4157-824b-b1f6220e83ad",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.synthesis import synth_clifford_bm\n",
        "from qiskit.transpiler.passes.synthesis.plugin import HighLevelSynthesisPlugin\n",
        "\n",
        "\n",
        "class MyCliffordSynthesisPlugin(HighLevelSynthesisPlugin):\n",
        "    def run(\n",
        "        self,\n",
        "        high_level_object,\n",
        "        coupling_map=None,\n",
        "        target=None,\n",
        "        qubits=None,\n",
        "        **options,\n",
        "    ) -> QuantumCircuit:\n",
        "        if high_level_object.num_qubits <= 3:\n",
        "            return synth_clifford_bm(high_level_object)\n",
        "        else:\n",
        "            return None"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1285dbfd-04ce-494b-8a01-a58040035dbd",
      "metadata": {},
      "source": [
        "Este plugin sintetiza objetos de tipo [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford) que tienen como máximo 3 qubits, utilizando el método `synth_clifford_bm` .\n",
        "\n",
        "Ahora, exponemos el plugin añadiendo un punto de entrada en los metadatos de nuestro paquete Python.\n",
        "Aquí, asumimos que la clase que definimos está expuesta en un módulo llamado `my_qiskit_plugin`, por ejemplo al ser importada en el archivo `__init__.py` del módulo `my_qiskit_plugin` .\n",
        "Editamos el archivo `pyproject.toml`, `setup.cfg`, o `setup.py` de nuestro paquete:\n",
        "\n",
        "<Tabs>\n",
        "  <TabItem value=\"package-table-toml\" label=\"pyproject.toml\" default>\n",
        "    ```toml\n",
        "    [project.entry-points.\"qiskit.synthesis\"]\n",
        "    \"clifford.my_clifford_synthesis\" = \"my_qiskit_plugin:MyCliffordSynthesisPlugin\"\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-cfg\" label=\"setup.cfg\">\n",
        "    ```ini\n",
        "    [options.entry_points]\n",
        "    qiskit.synthesis =\n",
        "        clifford.my_clifford_synthesis = my_qiskit_plugin:MyCliffordSynthesisPlugin\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-py\" label=\"setup.py\">\n",
        "    ```python\n",
        "    from setuptools import setup\n",
        "\n",
        "    setup(\n",
        "        # ...,\n",
        "        entry_points={\n",
        "            'qiskit.synthesis': [\n",
        "                'clifford.my_clifford_synthesis = my_qiskit_plugin:MyCliffordSynthesisPlugin',\n",
        "            ]\n",
        "        }\n",
        "    )\n",
        "    ```\n",
        "  </TabItem>\n",
        "</Tabs>\n",
        "\n",
        "`name` consta de dos partes separadas por un punto (`.`):\n",
        "\n",
        "* El nombre del tipo de [Operación](/docs/api/qiskit/qiskit.circuit.Operation) que sintetiza el plugin (en este caso, `clifford`). Nótese que esta cadena corresponde al atributo [`name`](/docs/api/qiskit/qiskit.circuit.Operation#name) de la clase Operation, y no al nombre de la clase en sí.\n",
        "* El nombre del plugin (en este caso, `special`).\n",
        "\n",
        "Al igual que antes, si su proyecto utiliza `setup.cfg` o `setup.py` en lugar de `pyproject.toml`, consulte la [documentación de setuptools](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) para saber cómo adaptar estas líneas a su situación.\n",
        "\n",
        "Para comprobar que tu plugin es detectado correctamente por Qiskit, instala tu paquete de plugins y sigue las instrucciones en [Transpiler plugins](transpiler-plugins#list-available-high-level-synthesis-plugins) para listar los plugins instalados, y asegúrate de que tu plugin aparece en la lista:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "fbe1f265",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['ag', 'bm', 'default', 'greedy', 'layers', 'lnn', 'rb_default']"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler.passes.synthesis import (\n",
        "    high_level_synthesis_plugin_names,\n",
        ")\n",
        "\n",
        "high_level_synthesis_plugin_names(\"clifford\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f1e86f49",
      "metadata": {},
      "source": [
        "Si nuestro plugin de ejemplo estuviera instalado, entonces el nombre `my_clifford_synthesis` aparecería en esta lista.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a48c2d0b-c402-4b83-ae2e-42c33fe1720e",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\" title=\"Recomendación\">\n",
        "  * [Envía tu plugin al Ecosistema Qiskit!](https://github.com/Qiskit/ecosystem?tab=readme-ov-file#how-to-join).\n",
        "  * Consulta los [tutoriales](/docs/tutorials) para ver ejemplos de transpilación y ejecución de circuitos cuánticos.\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": 5
}