{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "58b1f0a7-d62e-4f71-ba01-b8f0beaeeb83",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"トランスパイラープラグインを作成する\"\n",
        "description: \"Qiskit トランスパイラプラグインを作成して、トランスパイラコードをQiskitコミュニティと共有する方法\"\n",
        "---\n",
        "\n",
        "<span id=\"create-a-transpiler-plugin\" />\n",
        "\n",
        "# トランスパイラープラグインを作成する\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=\"パッケージ・バージョン\">\n",
        "    このページのコードは、以下の要件に基づいて開発された。\n",
        "    これらのバージョンまたは新しいバージョンの使用をお勧めします。\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": [
        "[トランスパイラープラグインを](transpiler-plugins)作成することは、あなたのトランスパイルコードをより広いQiskitコミュニティと共有する素晴らしい方法です。 Qiskitコミュニティへの貢献に関心をお寄せいただき、ありがとうございます！\n",
        "\n",
        "トランスパイラープラグインを作成する前に、どのようなプラグインがあなたの状況に適しているかを決める必要があります。 トランスパイラープラグインには3種類ある：\n",
        "\n",
        "* [**トランスパイラーステージプラグイン**](/docs/api/qiskit/transpiler_plugins)。 プリセット・ステージド・パス・マネージャーの [6つのステージの](transpiler-stages)うちの1つに置き換えられるパス・マネージャーを定義する場合に選択します。\n",
        "* [**ユニタリー・シンセシス・プラグイン**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin)。 ユニタリー行列（Numpyの配列として表現）を入力とし、そのユニタリーを実装した量子回路の記述を出力するトランスパイルコードを作成する場合に選択します。\n",
        "* [**高位合成プラグイン**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin)。 あなたのトランスパイルコードが、クリフォード演算子や線形関数のような「高レベルオブジェクト」を入力とし、その高レベルオブジェクトを実装した量子回路の記述を出力する場合、これを選択します。 高レベルのオブジェクトは、 [Operation](/docs/api/qiskit/qiskit.circuit.Operation) クラスのサブクラスで表される。\n",
        "\n",
        "作成するプラグインの種類が決まったら、以下の手順に従ってプラグインを作成します：\n",
        "\n",
        "1. 適切な抽象プラグイン・クラスのサブクラスを作成する：\n",
        "   * [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin) トランスパイラーステージプラグイン\n",
        "   * [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) ユニタリー・シンセシス・プラグインの場合\n",
        "   * [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) 高位合成プラグイン用。\n",
        "2. パッケージ・メタデータの [setuptoolsエントリ・ポイントとして](https://setuptools.pypa.io/en/latest/userguide/entry_point.html)クラスを公開します。通常は、 Python パッケージの `pyproject.toml`、 `setup.cfg`、または `setup.py` ファイルを編集します。\n",
        "\n",
        "1つのパッケージで定義できるプラグインの数に制限はありませんが、各プラグインには一意な名前が必要です。 Qiskit SDK自体には多くのプラグインが含まれており、その名前も予約されています。 予約名は以下の通り：\n",
        "\n",
        "* トランスパイラのステージプラグイン： [この表を](/docs/api/qiskit/transpiler_plugins#plugin-stages)参照してください。\n",
        "* 単体合成プラグイン： `default` `aqc`、 `sk`\n",
        "* ハイレベル・シンセシス・プラグイン：\n",
        "\n",
        "| オペレーションクラス                                                                                 | 操作名               | 予約名                                               |\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",
        "次のセクションでは、異なるタイプのプラグインについて、これらの手順の例を示します。 これらの例では、 `my_qiskit_plugin` という Python パッケージを作成すると仮定する。 Python パッケージの作成については、 Python ウェブサイトの[チュートリアルを](https://packaging.python.org/en/latest/tutorials/packaging-projects/)ご覧ください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4519c0dc-2bcd-48f4-8522-435b72efdb40",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-transpiler-stage-plugin\" />\n",
        "\n",
        "## 例: トランスパイラーステージプラグインを作成する\n",
        "\n",
        "この例では、 `layout` ステージ用のトランスパイラーステージプラグインを作成します（Qiskitの組み込みトランスパイルパイプラインの6つのステージの説明については、 [トランスパイラーステージを](transpiler-stages)参照してください）。\n",
        "私たちのプラグインは、単に [VF2Layout](/docs/api/qiskit/qiskit.transpiler.passes.VF2Layout) を実行するだけです。\n",
        "\n",
        "まず [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin). というメソッドを実装する必要がある。 [`pass_manager`](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin#pass_manager). このメソッドは [PassManagerConfig](/docs/api/qiskit/qiskit.transpiler.PassManagerConfig) を受け取り、定義しているパス・マネージャーを返します。 PassManagerConfig オブジェクトは、カップリング・マップやベーシス・ゲートなど、ターゲットのバックエンドに関する情報を格納している。\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": [
        "次に、 Python パッケージのメタデータにエントリー・ポイントを追加して、プラグインを公開する。\n",
        "`my_qiskit_plugin`例えば、 `my_qiskit_plugin` モジュールの `__init__.py` ファイルでインポートされる。\n",
        "パッケージの `pyproject.toml`、 `setup.cfg`、 `setup.py` ファイルを編集します（ 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": [
        "各トランスパイラステージのエントリーポイントと期待値については、 [トランスパイラープラグインステージの表を](/docs/api/qiskit/transpiler_plugins#stage-table)参照してください。\n",
        "\n",
        "プラグインがQiskitによって正常に検出されていることを確認するには、プラグインパッケージをインストールし、インストールされているプラグインを一覧表示するための [Transpiler pluginsの](transpiler-plugins#list-available-transpiler-stage-plugins)指示に従って、プラグインがリストに表示されていることを確認します：\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": [
        "この例のプラグインがインストールされていれば、 `my_layout` という名前がこのリストに表示される。\n",
        "\n",
        "組み込みのトランスパイラ・ステージをトランスパイラ・ステージ・プラグインの出発点として使いたい場合は、組み込みのトランスパイラ・ステージのパス・マネージャーを次のようにして入手できます。 [PassManagerStagePluginManager](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePluginManager#passmanagerstagepluginmanager). 次のコード・セルは、最適化レベル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",
        "## 例: ユニタリー合成プラグインを作成する\n",
        "\n",
        "この例では、単純に内蔵の [UnitarySynthesis](/docs/api/qiskit/qiskit.transpiler.passes.UnitarySynthesis#unitarysynthesis) トランスピレーション・パスを使用してゲートを合成します。 もちろん、あなた自身のプラグインはそれよりももっと面白いことをするだろう。\n",
        "\n",
        "この [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) クラスは、ユニタリー合成プラグイン プラグインを定義します。 主な方法は [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run), であり、入力としてユニタリー行列を格納するNumpy配列 を格納するNumpy配列を入力として受け取り、そのユニタリ行列から合成された回路を表す [DAGCircuitを](/docs/api/qiskit/qiskit.dagcircuit.DAGCircuit)返す。\n",
        "`run` メソッドに加えて、定義する必要のあるプロパティ・メソッドがいくつかある。\n",
        "参照 [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) を参照のこと。\n",
        "\n",
        "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": [
        "に利用可能な入力が少ないことが判明した場合 [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run) メソッドに利用可能な入力があなたの目的には不十分であるとお気づきの場合は、あなたの要件を説明する [issueを開いて](https://github.com/Qiskit/qiskit/issues/new/choose)ください。 オプション入力の追加など、プラグインのインターフェイスの変更は、既存のプラグインからの変更を必要としないよう、後方互換性のある方法で行われます。\n",
        "\n",
        "<Admonition type=\"note\" title=\"注\">\n",
        "  `supports_` というプレフィックスが付いたメソッドはすべて、 `UnitarySynthesisPlugin` の派生クラスでインターフェイスの一部として予約されている。 サブクラスには、抽象クラスで定義されていないカスタム・メソッド（ `supports_*` ）を定義してはならない。\n",
        "</Admonition>\n",
        "\n",
        "次に、 Python パッケージのメタデータにエントリー・ポイントを追加して、プラグインを公開する。\n",
        "`my_qiskit_plugin`例えば、 `my_qiskit_plugin` モジュールの `__init__.py` ファイルでインポートされる。\n",
        "パッケージの `pyproject.toml`、 `setup.cfg`、 `setup.py` ファイルを編集する：\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",
        "あなたのプロジェクトが `pyproject.toml` の代わりに `setup.cfg` または `setup.py` を使用している場合、あなたの状況に合わせてこれらの行を適応させる方法については、これまでと同様に [setuptoolsのドキュメントを](https://setuptools.pypa.io/en/latest/userguide/entry_point.html)参照してください。\n",
        "\n",
        "プラグインがQiskitによって正常に検出されていることを確認するには、プラグインパッケージをインストールし、インストールされているプラグインを一覧表示するための [Transpiler pluginsの](transpiler-plugins#list-available-unitary-synthesis-plugins)指示に従って、プラグインがリストに表示されていることを確認します：\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": [
        "この例のプラグインがインストールされていれば、 `my_unitary_synthesis` という名前がこのリストに表示される。\n",
        "\n",
        "複数のオプションを公開する単体合成プラグインに対応するため、プラグインインターフェースには、ユーザーが自由形式のオプションを指定できるようになっている、 プラグイン・インターフェイスには、ユーザーが自由形式の設定ディクショナリ 設定辞書を提供するオプションがあります。 これは、 `run` のキーワード引数を介して メソッドに渡される。 `options` に渡される。 プラグインにこのような設定オプションがある場合は、明確に文書化する必要があります。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "651c863d-41d9-41f4-a133-b392dae2f363",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-high-level-synthesis-plugin\" />\n",
        "\n",
        "## 例: ハイレベル合成プラグインを作成する\n",
        "\n",
        "この例では、組み込みの [synth\\_clifford\\_bm](/docs/api/qiskit/synthesis#synth_clifford_bm) 関数を使用してクリフォード演算子を合成するだけの高レベル合成プラグインを作成します。\n",
        "\n",
        "この [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) クラスは、高レベルの合成プラグインのインターフェースとコントラクトを定義します。 主な方法は [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin#run).\n",
        "位置引数 `high_level_object` は、合成される「高レベル」オブジェクトを表す [Operation](/docs/api/qiskit/qiskit.circuit.Operation) である。 例えば [LinearFunction](/docs/api/qiskit/qiskit.circuit.library.LinearFunction) であったり [クリフォード](/docs/api/qiskit/qiskit.quantum_info.Clifford)\n",
        "以下のキーワード引数がある：\n",
        "\n",
        "* `target` はターゲットのバックエンドを指定します。 がすべてのターゲット固有の情報にアクセスできるようにします、 カップリングマップやサポートされるゲートセットなど、ターゲット固有の情報にアクセスできるようになります。\n",
        "* `coupling_map` はカップリング・マップのみを指定し、 `target` が指定されていない場合にのみ使用される。\n",
        "* `qubits` 高レベルオブジェクトが定義される量子ビットのリストを指定します。 は、合成が物理回路上で行われる場合に、高レベルオブジェクトが定義される量子ビットのリストを指定します。\n",
        "  値が `None` の場合は、レイアウトがまだ選択されておらず、このオペレーションが操作されるターゲットまたはカップリング・マップの物理量子ビットがまだ決定されていないことを示す。\n",
        "* `options`プラグイン固有のオプションのための自由形式の設定辞書。 プラグインにこのような設定オプションがある場合は を明確に文書化する必要があります。\n",
        "\n",
        "`run` メソッドは [QuantumCircuit](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) を返します。\n",
        "また、 `None` を返すこともできます。これは、プラグインが指定された高レベルオブジェクトを合成できないことを示します。\n",
        "高レベルオブジェクトの実際の合成は [HighLevelSynthesis](/docs/api/qiskit/qiskit.transpiler.passes.HighLevelSynthesis) トランスパイラパスによって実行される。\n",
        "\n",
        "`run` メソッドに加えて、定義する必要のあるプロパティ・メソッドがいくつかある。\n",
        "参照 [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) を参照のこと。\n",
        "\n",
        "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": [
        "このプラグインは、以下のような [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford) 型のオブジェクトを合成する。 `synth_clifford_bm` 型のオブジェクトを合成します。\n",
        "\n",
        "次に、 Python パッケージのメタデータにエントリー・ポイントを追加して、プラグインを公開する。\n",
        "`my_qiskit_plugin`例えば、 `my_qiskit_plugin` モジュールの `__init__.py` ファイルでインポートされる。\n",
        "パッケージの `pyproject.toml`、 `setup.cfg`、 `setup.py` ファイルを編集する：\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` は、ドット(`.`)で区切られた2つの部分で構成されている：\n",
        "\n",
        "* プラグインが合成する [Operationの](/docs/api/qiskit/qiskit.circuit.Operation)タイプ名（この場合、 `clifford` ）。この文字列はOperationクラスの [`name`](/docs/api/qiskit/qiskit.circuit.Operation#name) 属性に対応し、クラス自体の名前ではないことに注意してください。\n",
        "* プラグインの名前（この場合は `special` ）。\n",
        "\n",
        "あなたのプロジェクトが `pyproject.toml` の代わりに `setup.cfg` または `setup.py` を使用している場合、あなたの状況に合わせてこれらの行を適応させる方法については、これまでと同様に [setuptoolsのドキュメントを](https://setuptools.pypa.io/en/latest/userguide/entry_point.html)参照してください。\n",
        "\n",
        "プラグインがQiskitによって正常に検出されていることを確認するには、プラグインパッケージをインストールし、インストールされているプラグインを一覧表示するための [Transpiler pluginsの](transpiler-plugins#list-available-high-level-synthesis-plugins)指示に従って、プラグインがリストに表示されていることを確認します：\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": [
        "この例のプラグインがインストールされていれば、 `my_clifford_synthesis` という名前がこのリストに表示される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a48c2d0b-c402-4b83-ae2e-42c33fe1720e",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\" title=\"勧告\">\n",
        "  * [Qiskitエコシステムにプラグインを投稿してください。](https://github.com/Qiskit/ecosystem?tab=readme-ov-file#how-to-join)\n",
        "  * 量子回路のトランスパイルと実行の例については、 [チュートリアルを](/docs/tutorials)チェックしてほしい。\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
}