Lewati ke konten utama

Membuat plugin transpiler

Versi paket

Kode di halaman ini dikembangkan menggunakan persyaratan berikut. Kami merekomendasikan menggunakan versi ini atau yang lebih baru.

qiskit[all]~=2.3.0

Membuat plugin transpiler adalah cara yang bagus untuk berbagi kode transpilasi kamu dengan komunitas Qiskit yang lebih luas, sehingga pengguna lain bisa memanfaatkan fungsionalitas yang sudah kamu kembangkan. Terima kasih atas minatmu untuk berkontribusi pada komunitas Qiskit!

Sebelum membuat plugin transpiler, kamu perlu memutuskan jenis plugin apa yang sesuai untuk situasimu. Ada tiga jenis plugin transpiler:

  • Plugin stage transpiler. Pilih ini jika kamu mendefinisikan sebuah pass manager yang bisa menggantikan salah satu dari 6 stage pada preset staged pass manager.
  • Plugin unitary synthesis. Pilih ini jika kode transpilasi kamu menerima input berupa matriks uniter (direpresentasikan sebagai array Numpy) dan menghasilkan deskripsi Circuit kuantum yang mengimplementasikan uniter tersebut.
  • Plugin high-level synthesis. Pilih ini jika kode transpilasi kamu menerima input berupa "objek high-level" seperti operator Clifford atau fungsi linear dan menghasilkan deskripsi Circuit kuantum yang mengimplementasikan objek high-level tersebut. Objek high-level direpresentasikan oleh subkelas dari kelas Operation.

Setelah menentukan jenis plugin yang akan dibuat, ikuti langkah-langkah berikut untuk membuat plugin:

  1. Buat subkelas dari kelas plugin abstrak yang sesuai:
  2. Ekspos kelas tersebut sebagai entry point setuptools di metadata paket, biasanya dengan mengedit file pyproject.toml, setup.cfg, atau setup.py untuk paket Python kamu.

Tidak ada batasan jumlah plugin yang bisa didefinisikan oleh satu paket, tetapi setiap plugin harus memiliki nama yang unik. Qiskit SDK sendiri menyertakan sejumlah plugin, yang namanya juga sudah dipesan. Nama-nama yang dipesan adalah:

  • Plugin stage transpiler: Lihat tabel ini.
  • Plugin unitary synthesis: default, aqc, sk
  • Plugin high-level synthesis:
Kelas OperationNama OperationNama yang dipesan
Cliffordclifforddefault, ag, bm, greedy, layers, lnn
LinearFunctionlinear_functiondefault, kms, pmh
PermutationGatepermutationdefault, kms, basic, acg, token_swapper

Di bagian selanjutnya, kami menampilkan contoh langkah-langkah ini untuk berbagai jenis plugin. Dalam contoh-contoh ini, kami mengasumsikan bahwa kita membuat paket Python bernama my_qiskit_plugin. Untuk informasi tentang membuat paket Python, kamu bisa melihat tutorial ini dari situs web Python.

Contoh: Membuat plugin stage transpiler​

Dalam contoh ini, kita membuat plugin stage transpiler untuk stage layout (lihat Transpiler stages untuk deskripsi 6 stage pipeline transpilasi bawaan Qiskit). Plugin kita cukup menjalankan VF2Layout untuk sejumlah percobaan yang bergantung pada level optimasi yang diminta.

Pertama, kita membuat subkelas dari PassManagerStagePlugin. Ada satu metode yang perlu diimplementasikan, bernama pass_manager. Metode ini menerima input berupa PassManagerConfig dan mengembalikan pass manager yang sedang kita definisikan. Objek PassManagerConfig menyimpan informasi tentang Backend target, seperti coupling map dan basis gate-nya.

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
# This import is needed for python versions prior to 3.10
from __future__ import annotations

from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import VF2Layout
from qiskit.transpiler.passmanager_config import PassManagerConfig
from qiskit.transpiler.preset_passmanagers import common
from qiskit.transpiler.preset_passmanagers.plugin import (
PassManagerStagePlugin,
)

class MyLayoutPlugin(PassManagerStagePlugin):
def pass_manager(
self,
pass_manager_config: PassManagerConfig,
optimization_level: int | None = None,
) -> PassManager:
layout_pm = PassManager(
[
VF2Layout(
coupling_map=pass_manager_config.coupling_map,
properties=pass_manager_config.backend_properties,
max_trials=optimization_level * 10 + 1,
target=pass_manager_config.target,
)
]
)
layout_pm += common.generate_embed_passmanager(
pass_manager_config.coupling_map
)
return layout_pm

Sekarang, kita ekspos plugin tersebut dengan menambahkan entry point di metadata paket Python kita. Di sini, kita mengasumsikan bahwa kelas yang kita definisikan diekspos dalam modul bernama my_qiskit_plugin, misalnya dengan diimpor di file __init__.py dari modul my_qiskit_plugin. Kita edit file pyproject.toml, setup.cfg, atau setup.py dari paket kita (tergantung jenis file yang kamu pilih untuk menyimpan metadata proyek Python):

[project.entry-points."qiskit.transpiler.layout"]
"my_layout" = "my_qiskit_plugin:MyLayoutPlugin"

Lihat tabel stage plugin transpiler untuk entry point dan ekspektasi setiap stage transpiler.

Untuk memastikan plugin kamu berhasil terdeteksi oleh Qiskit, instal paket plugin kamu dan ikuti instruksi di Plugin transpiler untuk membuat daftar plugin yang terinstal, dan pastikan plugin kamu muncul dalam daftar tersebut:

from qiskit.transpiler.preset_passmanagers.plugin import list_stage_plugins

list_stage_plugins("layout")
['default', 'dense', 'sabre', 'trivial']

Jika contoh plugin kita sudah terinstal, maka nama my_layout akan muncul dalam daftar ini.

Jika kamu ingin menggunakan stage transpiler bawaan sebagai titik awal untuk plugin stage transpiler kamu, kamu bisa mendapatkan pass manager untuk stage transpiler bawaan menggunakan PassManagerStagePluginManager. Sel kode berikut menunjukkan cara melakukan ini untuk mendapatkan stage optimasi bawaan untuk optimization level 3.

from qiskit.transpiler.preset_passmanagers.plugin import (
PassManagerStagePluginManager,
)

# Initialize the plugin manager
plugin_manager = PassManagerStagePluginManager()

# Here we create a pass manager config to use as an example.
# Instead, you should use the pass manager config that you already received as input
# to the pass_manager method of your PassManagerStagePlugin.
pass_manager_config = PassManagerConfig()

# Obtain the desired built-in transpiler stage
optimization = plugin_manager.get_passmanager_stage(
"optimization", "default", pass_manager_config, optimization_level=3
)

Contoh: Membuat plugin sintesis unitary​

Dalam contoh ini, kita akan membuat plugin sintesis unitary yang cukup menggunakan pass transpilasi bawaan UnitarySynthesis untuk mensintesis sebuah Gate. Tentu saja, plugin milikmu sendiri akan melakukan sesuatu yang lebih menarik dari itu.

Kelas UnitarySynthesisPlugin mendefinisikan antarmuka dan kontrak untuk plugin sintesis unitary. Metode utamanya adalah run, yang menerima array Numpy yang menyimpan matriks unitary sebagai input dan mengembalikan sebuah DAGCircuit yang merepresentasikan Circuit yang disintesis dari matriks unitary tersebut. Selain metode run, ada sejumlah metode property yang perlu didefinisikan. Lihat UnitarySynthesisPlugin untuk dokumentasi semua property yang diperlukan.

Mari kita buat subkelas UnitarySynthesisPlugin kita:

import numpy as np
from qiskit.circuit import QuantumCircuit, QuantumRegister
from qiskit.converters import circuit_to_dag
from qiskit.dagcircuit.dagcircuit import DAGCircuit
from qiskit.quantum_info import Operator
from qiskit.transpiler.passes import UnitarySynthesis
from qiskit.transpiler.passes.synthesis.plugin import UnitarySynthesisPlugin

class MyUnitarySynthesisPlugin(UnitarySynthesisPlugin):
@property
def supports_basis_gates(self):
# Returns True if the plugin can target a list of basis gates
return True

@property
def supports_coupling_map(self):
# Returns True if the plugin can synthesize for a given coupling map
return False

@property
def supports_natural_direction(self):
# Returns True if the plugin supports a toggle for considering
# directionality of 2-qubit gates
return False

@property
def supports_pulse_optimize(self):
# Returns True if the plugin can optimize pulses during synthesis
return False

@property
def supports_gate_lengths(self):
# Returns True if the plugin can accept information about gate lengths
return False

@property
def supports_gate_errors(self):
# Returns True if the plugin can accept information about gate errors
return False

@property
def supports_gate_lengths_by_qubit(self):
# Returns True if the plugin can accept information about gate lengths
# (The format of the input differs from supports_gate_lengths)
return False

@property
def supports_gate_errors_by_qubit(self):
# Returns True if the plugin can accept information about gate errors
# (The format of the input differs from supports_gate_errors)
return False

@property
def min_qubits(self):
# Returns the minimum number of qubits the plugin supports
return None

@property
def max_qubits(self):
# Returns the maximum number of qubits the plugin supports
return None

@property
def supported_bases(self):
# Returns a dictionary of supported bases for synthesis
return None

def run(self, unitary: np.ndarray, **options) -> DAGCircuit:
basis_gates = options["basis_gates"]
synth_pass = UnitarySynthesis(basis_gates, min_qubits=3)
qubits = QuantumRegister(3)
circuit = QuantumCircuit(qubits)
circuit.append(Operator(unitary).to_instruction(), qubits)
dag_circuit = synth_pass.run(circuit_to_dag(circuit))
return dag_circuit

Jika kamu menemukan bahwa input yang tersedia untuk metode run tidak mencukupi untuk kebutuhanmu, silakan buka issue yang menjelaskan kebutuhanmu. Perubahan pada antarmuka plugin, seperti penambahan input opsional tambahan, akan dilakukan dengan cara yang kompatibel ke belakang sehingga tidak memerlukan perubahan dari plugin yang sudah ada.

Catatan

Semua metode yang diawali dengan supports_ dicadangkan pada kelas turunan UnitarySynthesisPlugin sebagai bagian dari antarmuka. Kamu tidak boleh mendefinisikan metode supports_* kustom pada subkelas yang tidak didefinisikan dalam kelas abstrak.

Sekarang, kita ekspos plugin dengan menambahkan entry point pada metadata paket Python kita. Di sini, kita asumsikan bahwa kelas yang sudah kita definisikan diekspos dalam modul bernama my_qiskit_plugin, misalnya dengan diimpor di file __init__.py dari modul my_qiskit_plugin. Kita edit file pyproject.toml, setup.cfg, atau setup.py dari paket kita:

[project.entry-points."qiskit.unitary_synthesis"]
"my_unitary_synthesis" = "my_qiskit_plugin:MyUnitarySynthesisPlugin"

Seperti sebelumnya, jika proyekmu menggunakan setup.cfg atau setup.py alih-alih pyproject.toml, lihat dokumentasi setuptools untuk cara menyesuaikan baris-baris ini untuk situasimu.

Untuk memastikan plugin berhasil dideteksi oleh Qiskit, instal paket plugin kamu dan ikuti petunjuk di Plugin Transpiler untuk mendaftar plugin yang terinstal, dan pastikan plugin kamu muncul dalam daftar:

from qiskit.transpiler.passes.synthesis import unitary_synthesis_plugin_names

unitary_synthesis_plugin_names()
['aqc', 'clifford', 'default', 'gridsynth', 'sk']

Jika contoh plugin kita sudah terinstal, maka nama my_unitary_synthesis akan muncul dalam daftar ini.

Untuk mengakomodasi plugin sintesis unitary yang mengekspos beberapa opsi, antarmuka plugin memiliki opsi bagi pengguna untuk menyediakan kamus konfigurasi bebas. Ini akan diteruskan ke metode run melalui argumen kata kunci options. Jika plugin kamu memiliki opsi konfigurasi ini, kamu harus mendokumentasikannya dengan jelas.

Contoh: Membuat plugin sintesis tingkat tinggi​

Dalam contoh ini, kita akan membuat plugin sintesis tingkat tinggi yang cukup menggunakan fungsi bawaan synth_clifford_bm untuk mensintesis operator Clifford.

Kelas HighLevelSynthesisPlugin mendefinisikan antarmuka dan kontrak untuk plugin sintesis tingkat tinggi. Metode utamanya adalah run. Argumen posisional high_level_object adalah sebuah Operation yang merepresentasikan objek "tingkat tinggi" yang akan disintesis. Misalnya, bisa berupa LinearFunction atau sebuah Clifford. Argumen kata kunci berikut tersedia:

  • target menentukan Backend target, memungkinkan plugin untuk mengakses semua informasi spesifik target, seperti coupling map, set Gate yang didukung, dan sebagainya
  • coupling_map hanya menentukan coupling map, dan hanya digunakan ketika target tidak ditentukan.
  • qubits menentukan daftar Qubit di mana objek tingkat tinggi didefinisikan, jika sintesis dilakukan pada Circuit fisik. Nilai None menunjukkan bahwa tata letak belum dipilih dan Qubit fisik dalam target atau coupling map tempat operasi ini berlangsung belum ditentukan.
  • options, kamus konfigurasi bebas untuk opsi khusus plugin. Jika plugin kamu memiliki opsi konfigurasi ini kamu harus mendokumentasikannya dengan jelas.

Metode run mengembalikan sebuah QuantumCircuit yang merepresentasikan Circuit yang disintesis dari objek tingkat tinggi tersebut. Mengembalikan None juga diperbolehkan, yang menandakan bahwa plugin tidak dapat mensintesis objek tingkat tinggi yang diberikan. Sintesis aktual dari objek tingkat tinggi dilakukan oleh pass transpiler HighLevelSynthesis.

Selain metode run, ada sejumlah metode property yang perlu didefinisikan. Lihat HighLevelSynthesisPlugin untuk dokumentasi semua property yang diperlukan.

Mari kita definisikan subkelas HighLevelSynthesisPlugin kita:

from qiskit.synthesis import synth_clifford_bm
from qiskit.transpiler.passes.synthesis.plugin import HighLevelSynthesisPlugin

class MyCliffordSynthesisPlugin(HighLevelSynthesisPlugin):
def run(
self,
high_level_object,
coupling_map=None,
target=None,
qubits=None,
**options,
) -> QuantumCircuit:
if high_level_object.num_qubits <= 3:
return synth_clifford_bm(high_level_object)
else:
return None

Plugin ini mensintesis objek bertipe Clifford yang memiliki paling banyak 3 Qubit, menggunakan metode synth_clifford_bm.

Sekarang, kita ekspos plugin dengan menambahkan entry point pada metadata paket Python kita. Di sini, kita asumsikan bahwa kelas yang sudah kita definisikan diekspos dalam modul bernama my_qiskit_plugin, misalnya dengan diimpor di file __init__.py dari modul my_qiskit_plugin. Kita edit file pyproject.toml, setup.cfg, atau setup.py dari paket kita:

[project.entry-points."qiskit.synthesis"]
"clifford.my_clifford_synthesis" = "my_qiskit_plugin:MyCliffordSynthesisPlugin"

name terdiri dari dua bagian yang dipisahkan oleh titik (.):

  • Nama tipe Operation yang disintesis oleh plugin (dalam hal ini, clifford). Perlu diingat bahwa string ini sesuai dengan atribut name dari kelas Operation, bukan nama kelasnya itu sendiri.
  • Nama plugin (dalam hal ini, special).

Seperti sebelumnya, jika proyekmu menggunakan setup.cfg atau setup.py alih-alih pyproject.toml, lihat dokumentasi setuptools untuk cara menyesuaikan baris-baris ini untuk situasimu.

Untuk memastikan plugin berhasil dideteksi oleh Qiskit, instal paket plugin kamu dan ikuti petunjuk di Plugin Transpiler untuk mendaftar plugin yang terinstal, dan pastikan plugin kamu muncul dalam daftar:

from qiskit.transpiler.passes.synthesis import (
high_level_synthesis_plugin_names,
)

high_level_synthesis_plugin_names("clifford")
['ag', 'bm', 'default', 'greedy', 'layers', 'lnn', 'rb_default']

Jika contoh plugin kita sudah terinstal, maka nama my_clifford_synthesis akan muncul dalam daftar ini.

Rekomendasi
Source: IBM Quantum docs — updated 16 Mar 2026
English version on doQumentation — updated 7 Mei 2026
This translation based on the English version of 11 Mar 2026