إنشاء إضافة للمُحوِّل
إصدارات الحزم
تم تطوير الكود الموجود في هذه الصفحة باستخدام المتطلبات التالية. نوصي باستخدام هذه الإصدارات أو ما هو أحدث منها.
qiskit[all]~=2.3.0
إنشاء إضافة للمُحوِّل هو طريقة رائعة لمشاركة كود التحويل الخاص بك مع مجتمع Qiskit الأوسع، مما يتيح للمستخدمين الآخرين الاستفادة من الوظائف التي طوّرتها. شكرًا لاهتمامك بالمساهمة في مجتمع Qiskit!
قبل إنشاء إضافة للمُحوِّل، تحتاج إلى تحديد نوع الإضافة المناسب لحالتك. هناك ثلاثة أنواع من إضافات المُحوِّل:
- إضافة مرحلة المُحوِّل: اختر هذا النوع إذا كنت تُعرِّف مدير مسارات يمكن إحلاله محل إحدى المراحل الست لمدير المسارات المُهيَّأ مسبقًا.
- إضافة تركيب المصفوفة الأحادية: اختر هذا النوع إذا كان كود التحويل الخاص بك يأخذ كمدخل مصفوفة أحادية (ممثَّلة كمصفوفة Numpy) ويُخرج وصفًا لدائرة كمومية تُنفِّذ تلك المصفوفة الأحادية.
- إضافة التركيب عالي المستوى: اختر هذا النوع إذا كان كود التحويل الخاص بك يأخذ كمدخل "كائنًا عالي المستوى" مثل عامل Clifford أو دالة خطية ويُخرج وصفًا لدائرة كمومية تُنفِّذ ذلك الكائن عالي المستوى. تُمثَّل الكائنات عالية المستوى بواسطة فئات فرعية من فئة Operation.
بعد تحديد نوع الإضافة التي تريد إنشاءها، اتبع هذه الخطوات لإنشائها:
- أنشئ فئة فرعية من فئة الإضافة المجردة المناسبة:
- PassManagerStagePlugin لإضافة مرحلة المُحوِّل،
- UnitarySynthesisPlugin لإضافة تركيب المصفوفة الأحادية، و
- HighLevelSynthesisPlugin لإضافة التركيب عالي المستوى.
- اعرض الفئة كـنقطة دخول setuptools في بيانات تعريف الحزمة، وعادةً ما يكون ذلك بتعديل ملف
pyproject.tomlأوsetup.cfgأوsetup.pyالخاص بحزمتك في Python.
لا يوجد حد لعدد الإضافات التي يمكن أن تُعرِّفها حزمة واحدة، لكن يجب أن يكون لكل إضافة اسم فريد. يتضمن Qiskit SDK نفسه عددًا من الإضافات التي تحتل أسماءها محجوزة. الأسماء المحجوزة هي:
- إضافات مرحلة المُحوِّل: انظر هذا الجدول.
- إضافات تركيب المصفوفة الأحادية:
default،aqc،sk - إضافات التركيب عالي المستوى:
| فئة العملية | اسم العملية | الأسماء المحجوزة |
|---|---|---|
| Clifford | clifford | default، ag، bm، greedy، layers، lnn |
| LinearFunction | linear_function | default، kms، pmh |
| PermutationGate | permutation | default، kms، basic، acg، token_swapper |
في الأقسام التالية، نُقدِّم أمثلة على هذه الخطوات لأنواع الإضافات المختلفة. في هذه الأمثلة، نفترض أننا نُنشئ حزمة Python تُسمَّى my_qiskit_plugin. للاطلاع على معلومات حول إنشاء حزم Python، يمكنك الاطلاع على هذا البرنامج التعليمي من موقع Python.
مثال: إنشاء إضافة لمرحلة المُحوِّل
في هذا المثال، نُنشئ إضافة لمرحلة المُحوِّل الخاصة بمرحلة layout (انظر مراحل المُحوِّل للاطلاع على وصف المراحل الست لخط أنابيب التحويل المدمج في Qiskit).
تقوم إضافتنا ببساطة بتشغيل VF2Layout لعدد من المحاولات يعتمد على مستوى التحسين المطلوب.
أولًا، نُنشئ فئة فرعية من PassManagerStagePlugin. هناك طريقة واحدة نحتاج إلى تنفيذها تُسمَّى pass_manager. تأخذ هذه الطريقة كمدخل PassManagerConfig وتُعيد مدير المسارات الذي نُعرِّفه. يخزِّن كائن PassManagerConfig معلومات حول الـ Backend المستهدف، مثل خريطة الاقتران وبوابات الأساس.
# 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
الآن، نعرض الإضافة بإضافة نقطة دخول في بيانات تعريف حزمة Python الخاصة بنا.
نفترض هنا أن الفئة التي عرَّفناها مكشوفة في وحدة تُسمَّى my_qiskit_plugin، على سبيل المثال من خلال استيرادها في ملف __init__.py الخاص بوحدة my_qiskit_plugin.
نُعدِّل ملف pyproject.toml أو setup.cfg أو setup.py الخاص بحزمتنا (بحسب نوع الملف الذي اخترته لتخزين بيانات تعريف مشروع Python الخاص بك):
- pyproject.toml
- setup.cfg
- setup.py
[project.entry-points."qiskit.transpiler.layout"]
"my_layout" = "my_qiskit_plugin:MyLayoutPlugin"
[options.entry_points]
qiskit.transpiler.layout =
my_layout = my_qiskit_plugin:MyLayoutPlugin
from setuptools import setup
setup(
# ...,
entry_points={
'qiskit.transpiler.layout': [
'my_layout = my_qiskit_plugin:MyLayoutPlugin',
]
}
)
انظر جدول مراحل إضافة المُحوِّل للاطلاع على نقاط الدخول والمتطلبات الخاصة بكل مرحلة من مراحل المُحوِّل.
للتحقق من أن Qiskit يكتشف إضافتك بنجاح، ثبِّت حزمة الإضافة الخاصة بك واتبع التعليمات الموجودة في إضافات المُحوِّل لسرد الإضافات المثبَّتة، وتأكد من ظهور إضافتك في القائمة:
from qiskit.transpiler.preset_passmanagers.plugin import list_stage_plugins
list_stage_plugins("layout")
['default', 'dense', 'sabre', 'trivial']
لو كانت إضافتنا في المثال مثبَّتة، لظهر الاسم my_layout في هذه القائمة.
إذا أردت استخدام مرحلة مُحوِّل مدمجة كنقطة بداية لإضافة مرحلة المُحوِّل الخاصة بك، يمكنك الحصول على مدير المسارات لمرحلة مُحوِّل مدمجة باستخدام PassManagerStagePluginManager. تُوضِّح خلية الكود التالية كيفية القيام بذلك للحصول على مرحلة التحسين المدمجة لمستوى التحسين 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
)
مثال: إنشاء إضافة لتوليف الوحدانيات
في هذا المثال، سننشئ إضافة لتوليف الوحدانيات تستخدم ببساطة تمريرة التحويل المدمجة UnitarySynthesis لتوليف Gate. بالطبع، إضافتك الخاصة ستفعل شيئاً أكثر إثارةً من ذلك.
تُعرِّف فئة UnitarySynthesisPlugin الواجهة والعقد الخاص بإضافات توليف الوحدانيات. الطريقة الرئيسية هي
run،
التي تأخذ كمدخل مصفوفة Numpy تُخزّن مصفوفة وحدانية
وتُعيد DAGCircuit يُمثّل الدائرة المُولَّفة من تلك المصفوفة الوحدانية.
إلى جانب طريقة run، ثمّة عدد من طرق الخصائص التي يجب تعريفها.
راجع UnitarySynthesisPlugin للاطلاع على توثيق جميع الخصائص المطلوبة.
لنُنشئ الآن فئتنا الفرعية من UnitarySynthesisPlugin:
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
إذا وجدت أن المدخلات المتاحة لطريقة run
غير كافية لأغراضك، يُرجى فتح تذكرة توضّح فيها متطلباتك. التغييرات على واجهة الإضافة، كإضافة مدخلات اختيارية جديدة، ستُجرى بطريقة متوافقة مع الإصدارات السابقة بحيث لا تستلزم تعديلات من الإضافات الموجودة.
جميع الطرق التي تبدأ بـ supports_ محجوزة في الفئات المشتقة من UnitarySynthesisPlugin كجزء من الواجهة. لا تُعرِّف أي طرق supports_* مخصصة في فئة فرعية ما لم تكن مُعرَّفة في الفئة المجردة.
الآن، سنكشف عن الإضافة بإضافة نقطة دخول في بيانات تعريف حزمة Python الخاصة بنا.
نفترض هنا أن الفئة التي عرّفناها مكشوفة في وحدة تسمى my_qiskit_plugin، على سبيل المثال عبر استيرادها في ملف __init__.py الخاص بوحدة my_qiskit_plugin.
نُعدِّل ملف pyproject.toml أو setup.cfg أو setup.py في حزمتنا:
- pyproject.toml
- setup.cfg
- setup.py
[project.entry-points."qiskit.unitary_synthesis"]
"my_unitary_synthesis" = "my_qiskit_plugin:MyUnitarySynthesisPlugin"
[options.entry_points]
qiskit.unitary_synthesis =
my_unitary_synthesis = my_qiskit_plugin:MyUnitarySynthesisPlugin
from setuptools import setup
setup(
# ...,
entry_points={
'qiskit.unitary_synthesis': [
'my_unitary_synthesis = my_qiskit_plugin:MyUnitarySynthesisPlugin',
]
}
)
كما في السابق، إذا كان مشروعك يستخدم setup.cfg أو setup.py بدلاً من pyproject.toml، راجع توثيق setuptools لمعرفة كيفية تكييف هذه الأسطر لحالتك.
للتحقق من أن إضافتك اكتُشفت بنجاح بواسطة Qiskit، ثبِّت حزمة الإضافة واتبع التعليمات الموجودة في إضافات Transpiler لسرد الإضافات المثبتة، وتأكد من ظهور إضافتك في القائمة:
from qiskit.transpiler.passes.synthesis import unitary_synthesis_plugin_names
unitary_synthesis_plugin_names()
['aqc', 'clifford', 'default', 'gridsynth', 'sk']
لو كانت إضافتنا في المثال مثبَّتة، لظهر الاسم my_unitary_synthesis في هذه القائمة.
لاستيعاب إضافات توليف الوحدانيات التي تكشف عن خيارات متعددة،
تتضمن واجهة الإضافة خياراً يتيح للمستخدمين تمرير قاموس تكوين حر الصياغة. سيُمرَّر هذا القاموس إلى طريقة run
عبر وسيط الكلمة المفتاحية options. إذا كانت إضافتك تمتلك هذه الخيارات التكوينية، يجب عليك توثيقها بوضوح.
مثال: إنشاء إضافة للتوليف عالي المستوى
في هذا المثال، سننشئ إضافة للتوليف عالي المستوى تستخدم ببساطة الدالة المدمجة synth_clifford_bm لتوليف عامل Clifford.
تُعرِّف فئة HighLevelSynthesisPlugin الواجهة والعقد الخاص بإضافات التوليف عالي المستوى. الطريقة الرئيسية هي run.
الوسيط الموضعي high_level_object هو Operation يُمثّل الكائن "عالي المستوى" المراد توليفه. على سبيل المثال، يمكن أن يكون
LinearFunction أو
Clifford.
وسيطات الكلمات المفتاحية التالية متاحة:
- يُحدِّد
targetالـ Backend المستهدف، مما يتيح للإضافة الوصول إلى جميع المعلومات الخاصة بالهدف، كخريطة الاقتران، ومجموعة Gates المدعومة، وما إلى ذلك - يُحدِّد
coupling_mapخريطة الاقتران فقط، ويُستخدم فقط عندما لا يكونtargetمُحدَّداً. - يُحدِّد
qubitsقائمة Qubits التي يُعرَّف عليها الكائن عالي المستوى، في حالة إجراء التوليف على الدائرة المادية. تعني القيمةNoneأن التخطيط لم يُختَر بعد ولم يتحدد بعد أي Qubits المادية في الهدف أو خريطة الاقتران التي ستعمل عل يها هذه العملية. options، قاموس تكوين حر الصياغة لخيارات خاصة بالإضافة. إذا كانت إضافتك تمتلك هذه الخيارات التكوينية فيجب عليك توثيقها بوضوح.
تُعيد طريقة run دائرة QuantumCircuit
تُمثّل الدائرة المُولَّفة من ذلك الكائن عالي المستوى.
يُسمح أيضاً بإعادة None، مما يشير إلى أن الإضافة غير قادرة على توليف الكائن عالي المستوى المعطى.
يتولى التوليف الفعلي للكائنات عالية المستوى تمريرة الـ Transpiler
HighLevelSynthesis.
إلى جانب طريقة run، ثمّة عدد من طرق الخصائص التي يجب تعريفها.
راجع HighLevelSynthesisPlugin للاطلاع على توثيق جميع الخصائص المطلوبة.
لنُعرِّف الآن فئتنا الفرعية من HighLevelSynthesisPlugin:
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
تُولِّف هذه الإضافة كائنات من نوع Clifford التي تحتوي على
3 Qubits كحدٍّ أقصى، باستخدام طريقة synth_clifford_bm.
الآن، سنكشف عن الإضافة بإضافة نقطة دخول في بيانات تعريف حزمة Python الخاصة بنا.
نفترض هنا أن الفئة التي عرّفناها مكشوفة في وحدة تسمى my_qiskit_plugin، على سبيل المثال عبر استيرادها في ملف __init__.py الخاص بوحدة my_qiskit_plugin.
نُعدِّل ملف pyproject.toml أو setup.cfg أو setup.py في حز متنا:
- pyproject.toml
- setup.cfg
- setup.py
[project.entry-points."qiskit.synthesis"]
"clifford.my_clifford_synthesis" = "my_qiskit_plugin:MyCliffordSynthesisPlugin"
[options.entry_points]
qiskit.synthesis =
clifford.my_clifford_synthesis = my_qiskit_plugin:MyCliffordSynthesisPlugin
from setuptools import setup
setup(
# ...,
entry_points={
'qiskit.synthesis': [
'clifford.my_clifford_synthesis = my_qiskit_plugin:MyCliffordSynthesisPlugin',
]
}
)
يتكوّن الـ name من جزأين مفصولين بنقطة (.):
- اسم نوع Operation الذي تُولِّفه الإضافة (في هذه الحالة،
clifford). لاحظ أن هذه السلسلة تتوافق مع سمةnameالخاصة بفئة Operation، وليس اسم الفئة نفسها. - اسم الإضافة (في هذه الحالة،
special).
كما في السابق، إذا كان مشروعك يستخدم setup.cfg أو setup.py بدلاً من pyproject.toml، راجع توثيق setuptools لمعرفة كيفية تكييف هذه الأسطر لحالتك.
للتحقق من أن إضافتك اكتُشفت بنجاح بواسطة Qiskit، ثبِّت حزمة الإضافة واتبع التعليمات الموجودة في إضافات Transpiler لسرد الإضافات المثبتة، وتأكد من ظهور إضافتك في القائمة:
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']
لو كانت إضافتنا في المثال مثبَّتة، لظهر الاسم my_clifford_synthesis في هذه القائمة.
- أرسل إضافتك إلى نظام Qiskit البيئي!.
- اطّلع على الدروس التعليمية للاطلاع على أمثلة عن كيف ية تحويل وتشغيل دوائر الحوسبة الكمية.