انتقل إلى المحتوى الرئيسي

OpenQASM 2 وحزمة Qiskit SDK

Package versions

The code on this page was developed using the following requirements. We recommend using these versions or newer.

qiskit[all]~=2.3.0
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit

توفر حزمة Qiskit SDK بعض الأدوات للتحويل بين تمثيلات OpenQASM للبرامج الكمية وفئة QuantumCircuit.

استيراد برنامج OpenQASM 2 إلى Qiskit

هناك دالتان لاستيراد برامج OpenQASM 2 إلى Qiskit. وهما qasm2.load() التي تأخذ اسم ملف، وqasm2.loads() التي تأخذ برنامج OpenQASM 2 كنص (string).

import qiskit.qasm2

qiskit.qasm2.load(filename, include_path=('.',), include_input_directory='append', custom_instructions=(), custom_classical=(), strict=False)
qiskit.qasm2.loads(program, include_path=('.',), custom_instructions=(), custom_classical=(), strict=False)

راجع واجهة برمجة تطبيقات OpenQASM 2 في Qiskit لمزيد من المعلومات.

استيراد برامج بسيطة

بالنسبة لمعظم برامج OpenQASM 2، يمكنك استخدام qasm2.load وqasm2.loads بسيط مع وسيط واحد فقط.

مثال: استيراد برنامج OpenQASM 2 كنص

استخدم qasm2.loads() لاستيراد برنامج OpenQASM 2 كنص إلى QuantumCircuit:

import qiskit.qasm2

program = """
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];

h q[0];
cx q[0], q[1];

measure q -> c;
"""
circuit = qiskit.qasm2.loads(program)
circuit.draw()
┌───┐     ┌─┐
q_0: ┤ H ├──■──┤M├───
└───┘┌─┴─┐└╥┘┌─┐
q_1: ─────┤ X ├─╫─┤M├
└───┘ ║ └╥┘
c: 2/═══════════╩══╩═
0 1

مثال: استيراد برنامج OpenQASM 2 من ملف

استخدم load() لاستيراد برنامج OpenQASM 2 من ملف إلى QuantumCircuit:

import qiskit.qasm2
circuit = qiskit.qasm2.load("myfile.qasm")

ربط بوابات OpenQASM 2 ببوابات Qiskit

افتراضيًا، يتعامل مستورد OpenQASM 2 في Qiskit مع ملف الإدراج "qelib1.inc" باعتباره مكتبة قياسية فعلية. يتعامل المستورد مع هذا الملف على أنه يحتوي تحديدًا على البوابات الموصوفة في الورقة البحثية الأصلية التي تُعرّف OpenQASM 2. سيستخدم Qiskit البوابات المدمجة في مكتبة الدوائر لتمثيل البوابات الموجودة في "qelib1.inc". البوابات المعرَّفة في البرنامج عبر عبارات gate يدوية في OpenQASM 2 ستُبنى افتراضيًا كـفئات فرعية مخصصة من Gate في Qiskit.

يمكنك إخبار المستورد باستخدام فئات Gate محددة لعبارات gate التي يصادفها. يمكنك أيضًا استخدام هذه الآلية لمعاملة أسماء بوابات إضافية على أنها "مدمجة"، أي لا تحتاج إلى تعريف صريح. إذا حددت فئات البوابات المراد استخدامها لعبارات gate خارج "qelib1.inc"، فإن الدائرة الناتجة ستكون عادةً أكثر كفاءة للتعامل معها.

تحذير

اعتبارًا من Qiskit SDK v1.0، لا يزال مُصدِّر OpenQASM 2 في Qiskit (انظر تصدير دائرة Qiskit إلى OpenQASM 2) يتصرف كما لو أن "qelib1.inc" يحتوي على بوابات أكثر مما يحتوي عليه فعلًا. هذا يعني أن الإعدادات الافتراضية للمستورد قد لا تتمكن من استيراد برنامج صادر من مُصدِّرنا. راجع المثال المحدد للتعامل مع المُصدِّر القديم لحل هذه المشكلة.

هذا التناقض هو سلوك قديم في Qiskit، وسيُحل في إصدار لاحق منه.

لتمرير معلومات حول تعليمة مخصصة إلى مستورد OpenQASM 2، استخدم فئة qasm2.CustomInstruction. تتطلب هذه الفئة أربع قطع معلومات مطلوبة، بالترتيب:

  • اسم البوابة المستخدم في برنامج OpenQASM 2
  • عدد معاملات الزاوية التي تأخذها البوابة
  • عدد الكيوبتات التي تعمل عليها البوابة
  • فئة أو دالة Python المُنشِئة للبوابة، التي تأخذ معاملات البوابة (دون الكيوبتات) كوسائط منفردة

إذا صادف المستورد تعريف gate يطابق تعليمة مخصصة معطاة، فسيستخدم تلك المعلومات المخصصة لإعادة بناء كائن البوابة. إذا صودفت عبارة gate تطابق name تعليمة مخصصة، لكنها لا تطابق عدد المعاملات ولا عدد الكيوبتات، فسيُطلق المستورد خطأ QASM2ParseError للإشارة إلى عدم التطابق بين المعلومات المُقدَّمة والبرنامج.

بالإضافة إلى ذلك، يمكن تعيين وسيط خامس builtin اختياريًا إلى True لجعل البوابة متاحة تلقائيًا داخل برنامج OpenQASM 2، حتى لو لم تُعرَّف صراحةً. إذا صادف المستورد تعريف gate صريحًا لتعليمة مخصصة مدمجة، فسيقبله بصمت. كما سبق، إذا كان التعريف الصريح لنفس الاسم غير متوافق مع التعليمة المخصصة المُقدَّمة، فسيُطلق QASM2ParseError. هذا مفيد للتوافق مع مُصدِّرات OpenQASM 2 القديمة، ومع بعض منصات الحوسبة الكمية الأخرى التي تعامل "بوابات الأساس" في عتادها كتعليمات مدمجة.

يوفر Qiskit سمة بيانات للتعامل مع برامج OpenQASM 2 الصادرة من إصدارات قديمة من قدرات تصدير OpenQASM 2 في Qiskit. وهي qasm2.LEGACY_CUSTOM_INSTRUCTIONS، التي يمكن تمريرها كوسيط custom_instructions إلى qasm2.load() وqasm2.loads().

مثال: استيراد برنامج أنشأه مُصدِّر Qiskit القديم

يستخدم برنامج OpenQASM 2 هذا بوابات غير موجودة في النسخة الأصلية من "qelib1.inc" دون الإعلان عنها، لكنها بوابات قياسية في مكتبة Qiskit. يمكنك استخدام qasm2.LEGACY_CUSTOM_INSTRUCTIONS لإخبار المستورد بسهولة باستخدام نفس مجموعة البوابات التي كان مُصدِّر OpenQASM 2 في Qiskit يستخدمها سابقًا.

from qiskit import qasm2

program = """
OPENQASM 2.0;
include "qelib1.inc";

qreg q[4];
creg c[4];

h q[0];
cx q[0], q[1];

// 'rxx' is not actually in `qelib1.inc`,
// but Qiskit used to behave as if it were.
rxx(0.75) q[2], q[3];

measure q -> c;
"""
circuit = qasm2.loads(
program,
custom_instructions=qasm2.LEGACY_CUSTOM_INSTRUCTIONS,
)

مثال: استخدام فئة بوابة محددة عند استيراد برنامج OpenQASM 2

لا يستطيع Qiskit، بشكل عام، التحقق مما إذا كان التعريف في عبارة gate في OpenQASM 2 يتوافق تمامًا مع بوابة من مكتبة Qiskit القياسية. بدلًا من ذلك، يختار Qiskit بوابة مخصصة باستخدام التعريف الدقيق المُقدَّم. قد يكون هذا أقل كفاءة من استخدام إحدى البوابات القياسية المدمجة أو بوابة مخصصة يُعرِّفها المستخدم. يمكنك تعريف عبارات gate يدويًا بفئات محددة.

from qiskit import qasm2
from qiskit.circuit import Gate
from qiskit.circuit.library import RZXGate

# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])

custom_instructions = [
# Link the OpenQASM 2 name 'my' with our custom gate.
qasm2.CustomInstruction("my", 2, 1, MyGate),
# Link the OpenQASM 2 name 'rzx' with Qiskit's
# built-in RZXGate.
qasm2.CustomInstruction("rzx", 1, 2, RZXGate),
]

program = """
OPENQASM 2.0;

gate my(theta, phi) q {
U(theta / 2, phi, -theta / 2) q;
}
gate rzx(theta) a, b {
// It doesn't matter what definition is
// supplied, if the parameters match;
// Qiskit will still use `RZXGate`.
}

qreg q[2];
my(0.25, 0.125) q[0];
rzx(pi) q[0], q[1];
"""

circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)

مثال: تعريف بوابة مدمجة جديدة في برنامج OpenQASM 2

إذا تم تعيين الوسيط builtin=True، فلا تحتاج البوابة المخصصة إلى تعريف مرتبط بها.

from qiskit import qasm2
from qiskit.circuit import Gate

# Define a custom gate that takes one qubit and two angles.
class MyGate(Gate):
def __init__(self, theta, phi):
super().__init__("my", 1, [theta, phi])

custom_instructions = [
qasm2.CustomInstruction("my", 2, 1, MyGate, builtin=True),
]

program = """
OPENQASM 2.0;
qreg q[1];

my(0.25, 0.125) q[0];
"""

circuit = qasm2.loads(
program,
custom_instructions=custom_instructions,
)

تعريف دوال كلاسيكية مخصصة

يتضمن OpenQASM 2 بعض الدوال الكلاسيكية المدمجة للاستخدام في وسائط البوابات. يمكنك توسيع اللغة بدوال إضافية باستخدام وسيط custom_classical في qasm2.load() وqasm2.loads()، مع فئة qasm2.CustomClassical.

لتعريف دالة كلاسيكية مخصصة، يجب عليك توفير:

  • اسم الدالة كما يظهر في برنامج OpenQASM 2
  • عدد وسائط الفاصلة العائمة التي تقبلها
  • كائن Python قابل للاستدعاء يُقيِّم الدالة

جميع الدوال الكلاسيكية المخصصة المُعرَّفة تُعامَل كمدمجة في لغة OpenQASM 2 من قِبل المستورد. لا توجد طريقة رسمية داخل لغة OpenQASM 2 لتعريف دوال جديدة؛ هذا امتداد خاص بـQiskit.

مثال: استخدام تعليمات كلاسيكية مخصصة

هنا نوفر دالتين كلاسيكيتين مخصصتين. الأولى بسيطة، وتضيف فقط واحدًا إلى مدخلاتها. الثانية هي الدالة math.atan2، التي تمثل العملية الرياضية arctan(y/x)\arctan(y/x) بطريقة تراعي الربع.

import math
from qiskit import qasm2

program = """
include "qelib1.inc";
qreg q[2];
rx(arctan(pi, 3 + add_one(0.2))) q[0];
cx q[0], q[1];
"""

def add_one(x):
return x + 1

customs = [
# Our `add_one` takes only one parameter.
qasm2.CustomClassical("add_one", 1, add_one),
# `arctan` takes two parameters, and `math.atan2` implements it.
qasm2.CustomClassical("arctan", 2, math.atan2),
]
circuit = qasm2.loads(program, custom_classical=customs)

الوضع الصارم

افتراضيًا، يكون هذا المُحلِّل أكثر مرونة من المواصفات الرسمية. يسمح بالفواصل الزائدة في قوائم المعاملات؛ وبالفاصلة المنقوطة غير الضرورية (عبارة فارغة)؛ وبحذف عبارة الإصدار OPENQASM 2.0;؛ وعدة تحسينات أخرى على جودة الحياة دون إصدار أي أخطاء. ومع ذلك، يمكنك استخدام وضع "حرفية المواصفة" عبر strict=True.

تصدير دائرة Qiskit إلى OpenQASM 2

يمكن لـQiskit أيضًا تصدير QuantumCircuit إلى OpenQASM 2. تستخدم الدالة qasm2.dump() للكتابة إلى ملف، وqasm2.dumps() للكتابة إلى نص. تمتلك هاتان الدالتان حاليًا واجهة بسيطة جدًا: تقبلان دائرة، وفي حالة qasm2.dump() فقط، موقعًا لكتابة المخرجات إليه.

تحذير

لا يزال مُصدِّر OpenQASM 2 في Qiskit يفترض نسخة قديمة وغير قياسية من ملف الإدراج "qelib1.inc". سيُحل هذا في إصدار لاحق من Qiskit، لكن في هذه الأثناء، إذا كنت بحاجة لإعادة استيراد برنامج OpenQASM 2 أنشأته باستخدام Qiskit، فاستخدم المثال أعلاه لإخبار المستورد ببوابات الإصدار القديم.

مثال: تصدير دائرة إلى OpenQASM 2

from qiskit import QuantumCircuit, qasm2

# Define any circuit.
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure([0, 1], [0, 1])

# Export to a string.
program = qasm2.dumps(circuit)

# Export to a file.
qasm2.dump(circuit, "my_file.qasm")

الخطوات التالية

توصيات