{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "58b1f0a7-d62e-4f71-ba01-b8f0beaeeb83",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Crea un plugin transpiler\"\n",
        "description: \"Come creare un plugin transpiler Qiskit per condividere il tuo codice di transpilazione con la comunità Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"create-a-transpiler-plugin\" />\n",
        "\n",
        "# Crea un plugin transpiler\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=\"Versioni del pacchetto\">\n",
        "    Il codice di questa pagina è stato sviluppato in base ai seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o versioni più recenti.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.1\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a7f87a76-b7a1-4dbb-ad45-55ff63c4665b",
      "metadata": {},
      "source": [
        "La creazione di un [plugin per il transpiler](transpiler-plugins) è un ottimo modo per condividere il codice di transpilazione con la comunità di Qiskit, consentendo ad altri utenti di beneficiare delle funzionalità sviluppate. Grazie per il vostro interesse a contribuire alla comunità di Qiskit!\n",
        "\n",
        "Prima di creare un plugin per il transpiler, è necessario decidere quale tipo di plugin è adatto alla propria situazione. Esistono tre tipi di plugin di transpiler:\n",
        "\n",
        "* [**Plugin per palcoscenico Transpiler**](/docs/api/qiskit/transpiler_plugins). Scegliere questa opzione se si sta definendo un gestore di passaggi che può essere sostituito da uno dei [6 stadi](transpiler-stages) di un gestore di passaggi preimpostato.\n",
        "* [**Plugin di sintesi unitaria**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin). Scegliere questa opzione se il codice di transpilazione prende in input una matrice unitaria (rappresentata come array Numpy) e produce una descrizione di un circuito quantistico che implementa tale matrice unitaria.\n",
        "* [**Plugin di sintesi ad alto livello**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin). Scegliere questa opzione se il codice di transpilazione prende in input un \"oggetto di alto livello\", come un operatore di Clifford o una funzione lineare, e restituisce una descrizione di un circuito quantistico che implementa quell'oggetto di alto livello. Gli oggetti di alto livello sono rappresentati da sottoclassi della classe [Operation](/docs/api/qiskit/qiskit.circuit.Operation).\n",
        "\n",
        "Una volta stabilito quale tipo di plugin creare, seguire i seguenti passaggi per creare il plugin:\n",
        "\n",
        "1. Creare una sottoclasse della classe astratta del plugin appropriata:\n",
        "   * [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin) per un plugin dello stadio transpiler,\n",
        "   * [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) per un plugin di sintesi unitario e\n",
        "   * [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) per un plugin di sintesi di alto livello.\n",
        "2. Esporre la classe come [punto di ingresso di setuptools](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) nei metadati del pacchetto, in genere modificando i file `pyproject.toml`, `setup.cfg`, o `setup.py` per il pacchetto Python.\n",
        "\n",
        "Non c'è limite al numero di plugin che un singolo pacchetto può definire, ma ogni plugin deve avere un nome unico. Lo stesso SDK di Qiskit include una serie di plugin, i cui nomi sono anch'essi riservati. I nomi riservati sono:\n",
        "\n",
        "* Plugin dello stage Transpiler: Vedere [questa tabella](/docs/api/qiskit/transpiler_plugins#plugin-stages).\n",
        "* Plugin di sintesi unitaria: `default`, `aqc`, `sk`\n",
        "* Plugin di sintesi ad alto livello:\n",
        "\n",
        "| Classe di funzionamento                                                                    | Nome operazione   | Nomi riservati                                    |\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",
        "Nelle prossime sezioni verranno mostrati esempi di questi passaggi per i diversi tipi di plugin. In questi esempi, si ipotizza di creare un pacchetto Python chiamato `my_qiskit_plugin`. Per informazioni sulla creazione di pacchetti Python, potete consultare [questo tutorial](https://packaging.python.org/en/latest/tutorials/packaging-projects/) dal sito 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",
        "## Esempio: Creare un plugin per la fase di transpilazione\n",
        "\n",
        "In questo esempio, creiamo un plugin per lo stage del transpiler per lo stage `layout` (vedere [Stadi del transpiler per](transpiler-stages) una descrizione dei 6 stadi della pipeline di transpilazione integrata di Qiskit).\n",
        "Il nostro plugin esegue semplicemente [VF2Layout](/docs/api/qiskit/qiskit.transpiler.passes.VF2Layout) per un numero di prove che dipende dal livello di ottimizzazione richiesto.\n",
        "\n",
        "Per prima cosa, creiamo una sottoclasse di [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin). C'è un metodo che dobbiamo implementare, chiamato [`pass_manager`](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin#pass_manager). Questo metodo prende in input un oggetto [PassManagerConfig](/docs/api/qiskit/qiskit.transpiler.PassManagerConfig) e restituisce il gestore di passaggi che stiamo definendo. L'oggetto PassManagerConfig memorizza informazioni sul backend di destinazione, come la sua mappa di accoppiamento e le porte di 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": [
        "Ora, esponiamo il plugin aggiungendo un punto di ingresso nei metadati del nostro pacchetto Python.\n",
        "In questo caso, si assume che la classe definita sia esposta in un modulo chiamato `my_qiskit_plugin`, ad esempio importata nel file `__init__.py` del modulo `my_qiskit_plugin` .\n",
        "Modifichiamo il file `pyproject.toml`, `setup.cfg` o `setup.py` del nostro pacchetto (a seconda del tipo di file scelto per memorizzare i metadati del progetto 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": [
        "Consultare la [tabella delle fasi del plugin transpiler](/docs/api/qiskit/transpiler_plugins#stage-table) per i punti di ingresso e le aspettative per ciascuna fase del transpiler.\n",
        "\n",
        "Per verificare che il vostro plugin sia stato rilevato con successo da Qiskit, installate il vostro pacchetto di plugin e seguite le istruzioni riportate in [Transpiler plugins](transpiler-plugins#list-available-transpiler-stage-plugins) per l'elenco dei plugin installati e assicuratevi che il vostro plugin appaia nell'elenco:\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": [
        "Se il nostro plugin di esempio fosse installato, in questo elenco comparirebbe il nome `my_layout` .\n",
        "\n",
        "Se si vuole usare uno stadio transpiler incorporato come punto di partenza per il proprio plugin di stadio transpiler, si può ottenere il gestore di pass per uno stadio transpiler incorporato usando [PassManagerStagePluginManager](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePluginManager#passmanagerstagepluginmanager). La seguente cella di codice mostra come eseguire questa operazione per ottenere lo stadio di ottimizzazione incorporato per il livello di ottimizzazione 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",
        "## Esempio: Creare un plugin di sintesi unitario\n",
        "\n",
        "In questo esempio, creeremo un plugin di sintesi unitaria che utilizza semplicemente il passaggio di transpilazione integrato per sintetizzare un gate [UnitarySynthesis](/docs/api/qiskit/qiskit.transpiler.passes.UnitarySynthesis#unitarysynthesis) per sintetizzare un gate. Naturalmente, il vostro plugin farà qualcosa di più interessante di questo.\n",
        "\n",
        "La classe [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) definisce l'interfaccia e il contratto per i plugin di sintesi unitaria plugin. Il metodo principale è [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run), che prende in input un array Numpy che memorizza una matrice unitaria e restituisce un [DAGCircuit](/docs/api/qiskit/qiskit.dagcircuit.DAGCircuit) che rappresenta il circuito sintetizzato da quella matrice unitaria.\n",
        "Oltre al metodo `run` , è necessario definire una serie di metodi di proprietà.\n",
        "Vedere [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) per la documentazione di tutte le proprietà richieste.\n",
        "\n",
        "Creiamo la nostra sottoclasse 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": [
        "Se si scopre che gli ingressi disponibili per il sistema [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run) sono insufficienti per i vostri scopi, [aprite un problema](https://github.com/Qiskit/qiskit/issues/new/choose) spiegando le vostre esigenze. Le modifiche all'interfaccia del plugin, come l'aggiunta di ulteriori ingressi opzionali, saranno effettuate in modo retrocompatibile, in modo da non richiedere modifiche ai plugin esistenti.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Nota\">\n",
        "  Tutti i metodi con prefisso `supports_` sono riservati a una classe derivata da `UnitarySynthesisPlugin` come parte dell'interfaccia. Non si devono definire metodi `supports_*` personalizzati su una sottoclasse che non siano definiti nella classe astratta.\n",
        "</Admonition>\n",
        "\n",
        "Ora, esponiamo il plugin aggiungendo un punto di ingresso nei metadati del nostro pacchetto Python.\n",
        "In questo caso, si assume che la classe definita sia esposta in un modulo chiamato `my_qiskit_plugin`, ad esempio importata nel file `__init__.py` del modulo `my_qiskit_plugin` .\n",
        "Modifichiamo il file `pyproject.toml`, `setup.cfg` o `setup.py` del nostro pacchetto:\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",
        "Come prima, se il tuo progetto utilizza `setup.cfg` O `setup.py` invece di `pyproject.toml`, consulta la [documentazione di setuptools](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) per sapere come adattare queste righe alla tua situazione.\n",
        "\n",
        "Per verificare che il vostro plugin sia stato rilevato con successo da Qiskit, installate il vostro pacchetto di plugin e seguite le istruzioni riportate in [Transpiler plugins](transpiler-plugins#list-available-unitary-synthesis-plugins) per l'elenco dei plugin installati e assicuratevi che il vostro plugin appaia nell'elenco:\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": [
        "Se il nostro plugin di esempio fosse installato, in questo elenco comparirebbe il nome `my_unitary_synthesis` .\n",
        "\n",
        "Per accogliere i plugin di sintesi unitaria che espongono più opzioni, l'interfaccia del plugin ha un'opzione che consente agli utenti di fornire un dizionario di configurazione dizionario di configurazione. Questo verrà passato al metodo `run` tramite l'argomento della parola chiave `options` . Se il vostro plugin ha queste opzioni di configurazione, dovreste documentarle chiaramente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "651c863d-41d9-41f4-a133-b392dae2f363",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-high-level-synthesis-plugin\" />\n",
        "\n",
        "## Esempio: Creare un plugin di sintesi di alto livello\n",
        "\n",
        "In questo esempio, creeremo un plugin di sintesi di alto livello che utilizza semplicemente la funzione integrata [synth\\_clifford\\_bm](/docs/api/qiskit/synthesis#synth_clifford_bm) per sintetizzare un operatore Clifford.\n",
        "\n",
        "La classe [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) definisce l'interfaccia e il contratto per i plugin di sintesi di alto livello. Il metodo primario è [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin#run).\n",
        "L'argomento posizionale `high_level_object` è un' [operazione](/docs/api/qiskit/qiskit.circuit.Operation) che rappresenta l'oggetto di \"alto livello\" da sintetizzare. Ad esempio, potrebbe essere un [LinearFunction](/docs/api/qiskit/qiskit.circuit.library.LinearFunction) o un [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford).\n",
        "Sono presenti i seguenti argomenti di parole chiave:\n",
        "\n",
        "* `target` specifica il backend di destinazione, consentendo al plugin di accedere a tutte le informazioni specifiche del target, come la mappa di accoppiamento, l'insieme dei gate supportati e così via\n",
        "* `coupling_map` specifica solo la mappa di accoppiamento e viene utilizzato solo quando `target` non è specificato.\n",
        "* `qubits` specifica l'elenco dei qubit su cui viene definito l'oggetto di alto livello, nel caso in cui la sintesi venga effettuata sul circuito fisico di alto livello, nel caso in cui la sintesi venga effettuata sul circuito fisico.\n",
        "  Un valore di `None` indica che il layout non è ancora stato scelto e che i qubit fisici nella mappa di destinazione o di accoppiamento su cui opera questa operazione non sono ancora stati determinati.\n",
        "* `options`, un dizionario di configurazione a forma libera per le opzioni specifiche del plugin. Se il plugin ha queste opzioni di configurazione dovrebbe documentarle chiaramente.\n",
        "\n",
        "Il metodo `run` restituisce un oggetto [QuantumCircuit](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) che rappresenta il circuito sintetizzato da quell'oggetto di alto livello.\n",
        "Può anche restituire `None`, indicando che il plugin non è in grado di sintetizzare l'oggetto di alto livello indicato.\n",
        "La sintesi vera e propria degli oggetti di alto livello viene eseguita dal programma [HighLevelSynthesis](/docs/api/qiskit/qiskit.transpiler.passes.HighLevelSynthesis) transpiler.\n",
        "\n",
        "Oltre al metodo `run` , è necessario definire una serie di metodi di proprietà.\n",
        "Vedere [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) per la documentazione di tutte le proprietà richieste.\n",
        "\n",
        "Definiamo la nostra sottoclasse 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": [
        "Questo plugin sintetizza oggetti di tipo [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford) che hanno al massimo 3 qubit, utilizzando il metodo `synth_clifford_bm` .\n",
        "\n",
        "Ora, esponiamo il plugin aggiungendo un punto di ingresso nei metadati del nostro pacchetto Python.\n",
        "In questo caso, si assume che la classe definita sia esposta in un modulo chiamato `my_qiskit_plugin`, ad esempio importata nel file `__init__.py` del modulo `my_qiskit_plugin` .\n",
        "Modifichiamo il file `pyproject.toml`, `setup.cfg` o `setup.py` del nostro pacchetto:\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` è composto da due parti separate da un punto (`.`):\n",
        "\n",
        "* Il nome del tipo di [operazione](/docs/api/qiskit/qiskit.circuit.Operation) che il plugin sintetizza (in questo caso, `clifford`). Si noti che questa stringa corrisponde all'attributo [`name`](/docs/api/qiskit/qiskit.circuit.Operation#name) della classe Operation e non al nome della classe stessa.\n",
        "* Il nome del plugin (in questo caso, `special`).\n",
        "\n",
        "Come prima, se il tuo progetto utilizza `setup.cfg` O `setup.py` invece di `pyproject.toml`, consulta la [documentazione di setuptools](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) per sapere come adattare queste righe alla tua situazione.\n",
        "\n",
        "Per verificare che il vostro plugin sia stato rilevato con successo da Qiskit, installate il vostro pacchetto di plugin e seguite le istruzioni riportate in [Transpiler plugins](transpiler-plugins#list-available-high-level-synthesis-plugins) per l'elenco dei plugin installati e assicuratevi che il vostro plugin appaia nell'elenco:\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": [
        "Se il nostro plugin di esempio fosse installato, in questo elenco comparirebbe il nome `my_clifford_synthesis` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a48c2d0b-c402-4b83-ae2e-42c33fe1720e",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\" title=\"Suggerimento\">\n",
        "  * [Invia il tuo plugin all'ecosistema Qiskit!](https://github.com/Qiskit/ecosystem?tab=readme-ov-file#how-to-join)\n",
        "  * Consultate le [esercitazioni](/docs/tutorials) per trovare esempi di transpiling e di esecuzione di circuiti quantistici.\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
}