تدريب النواة الكمية
تقدير الاستخدام: أقل من دقيقة واحدة على معالج Eagle r3 (ملاحظة: هذا تقدير فقط. قد يختلف وقت التشغيل الفعلي.)
الخلفية
يوضح هذا البرنامج التعليمي كيفية بناء Qiskit pattern لتقييم عناصر مصفوفة النواة الكمية المستخدمة في التصنيف الثنائي. لمزيد من المعلومات حول Qiskit patterns وكيف يمكن استخدام Qiskit Serverless لنشرها على السحابة للتنفيذ المُدار، تفضل بزيارة صفحة الوثائق الخاصة بمنصة IBM Quantum®.
المتطلبات
قبل البدء في هذا البرنامج التعليمي، تأكد من تثبيت ما يلي:
- Qiskit SDK الإصدار 1.0 أو أحدث، مع دعم التمثيل البصري
- Qiskit Runtime الإصدار 0.22 أو أحدث (
pip install qiskit-ibm-runtime)
الإعداد
!wget https://raw.githubusercontent.com/qiskit-community/prototype-quantum-kernel-training/main/data/dataset_graph7.csv
# General Imports and helper functions
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from qiskit.circuit import Parameter, ParameterVector, QuantumCircuit
from qiskit.circuit.library import UnitaryOverlap
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
# from qiskit_serverless import IBMServerlessClient, QiskitFunction
from qiskit_ibm_catalog import QiskitServerless, QiskitFunction
def visualize_counts(res_counts, num_qubits, num_shots):
"""Visualize the outputs from the Qiskit Sampler primitive."""
zero_prob = res_counts.get(0, 0.0)
top_10 = dict(
sorted(res_counts.items(), key=lambda item: item[1], reverse=True)[
:10
]
)
top_10.update({0: zero_prob})
by_key = dict(sorted(top_10.items(), key=lambda item: item[0]))
x_vals, y_vals = list(zip(*by_key.items()))
x_vals = [bin(x_val)[2:].zfill(num_qubits) for x_val in x_vals]
y_vals_prob = []
for t in range(len(y_vals)):
y_vals_prob.append(y_vals[t] / num_shots)
y_vals = y_vals_prob
plt.bar(x_vals, y_vals)
plt.xticks(rotation=75)
plt.title("Results of sampling")
plt.xlabel("Measured bitstring")
plt.ylabel("Probability")
plt.show()
def get_training_data():
"""Read the training data."""
df = pd.read_csv("dataset_graph7.csv", sep=",", header=None)
training_data = df.values[:20, :]
ind = np.argsort(training_data[:, -1])
X_train = training_data[ind][:, :-1]
return X_train
7[1A[1G[27G[Files: 0 Bytes: 0 [0 B/s] Re]87[2A[1G[27G[https://raw.githubusercontent.]87[1S[3A[1G[0JSaving 'dataset_graph7.csv.1'
87[2A[1Gdataset_graph7.csv.1 100% [=============================>] 20.25K --.-KB/s87[1S[3A[1G[0JHTTP response 200 [https://raw.githubusercontent.com/qiskit-community/prototype-quantum-kernel-training/main/data/dataset_graph7.csv]
87[2A[1Gdataset_graph7.csv.1 100% [=============================>] 20.25K --.-KB/s87[1A[1G[27G[Files: 1 Bytes: 20.25K [93.33]8[m[m[m[m
الخطوة 1: تحويل المدخلات الكلاسيكية إلى مسألة كمية
- المدخل: مجموعة بيانات التدريب.
- المخرج: دائرة مجردة لحساب عنصر في مصفوفة النواة.
أنشئ الدائرة الكمية المستخدمة لتقييم عنصر واحد في مصفوفة النواة. نستخدم بيانات الإدخال لتحديد زوايا الدوران لبوابات الدائرة ذات المعاملات. سنستخدم عينتي البيانات x1=14 وx2=19.
ملاحظة: يمكن تنزيل مجموعة البيانات المستخدمة في هذا البرنامج التعليمي من هنا.
# Prepare training data
X_train = get_training_data()
# Empty kernel matrix
num_samples = np.shape(X_train)[0]
kernel_matrix = np.full((num_samples, num_samples), np.nan)
# Prepare feature map for computing overlap
num_features = np.shape(X_train)[1]
num_qubits = int(num_features / 2)
entangler_map = [[0, 2], [3, 4], [2, 5], [1, 4], [2, 3], [4, 6]]
fm = QuantumCircuit(num_qubits)
training_param = Parameter("θ")
feature_params = ParameterVector("x", num_qubits * 2)
fm.ry(training_param, fm.qubits)
for cz in entangler_map:
fm.cz(cz[0], cz[1])
for i in range(num_qubits):
fm.rz(-2 * feature_params[2 * i + 1], i)
fm.rx(-2 * feature_params[2 * i], i)
# Assign tunable parameter to known optimal value and set the data params for first two samples
x1 = 14
x2 = 19
unitary1 = fm.assign_parameters(list(X_train[x1]) + [np.pi / 2])
unitary2 = fm.assign_parameters(list(X_train[x2]) + [np.pi / 2])
# Create the overlap circuit
overlap_circ = UnitaryOverlap(unitary1, unitary2)
overlap_circ.measure_all()
overlap_circ.draw("mpl", scale=0.6, style="iqp")
الخطوة 2: تحسين المسألة لتنفيذها على العتاد الكمي
- المدخل: دائرة مجردة غير محسَّنة لواجهة خلفية بعينها
- المخرج: الدائرة الهدف والمرصد، محسَّنان للوحدة المعالجة الكمية المختارة
استخدم الدالة generate_preset_pass_manager من Qiskit لتحديد روتين التحسين لدائرتنا فيما يخص وحدة المعالجة الكمية التي نخطط لتشغيل التجربة عليها. نضبط optimization_level=3، مما يعني أننا سنستخدم مدير التمريرات المعدّ مسبقاً الذي يوفر أعلى مستوى من التحسين.
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=overlap_circ.num_qubits
)
pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
overlap_ibm = pm.run(overlap_circ)
overlap_ibm.draw("mpl", scale=0.6, idle_wires=False, fold=-1, style="iqp")
الخطوة 3: التنفيذ باستخدام العناصر الأولية لـ Qiskit
- المدخل: الدائرة الهدف
- المخرج: توزيع الاحتمالات شبه الدقيقة
استخدم العنصر الأولي Sampler من Qiskit Runtime لإعادة بناء توزيع الاحتمالات شبه الدقيقة للحالات الناتجة عن أخذ عينات من الدائرة. لغرض توليد مصفوفة النواة، نهتم بشكل خاص باحتمال قياس الحالة |0>.
في هذا العرض التوضيحي، سنشغّل على وحدة معالجة كمية باستخدام العناصر الأولية لـ qiskit-ibm-runtime. للتشغيل على العناصر الأولية المبنية على متجه الحالة في qiskit، استبدل كتلة الكود التي تستخدم العناصر الأولية لـ Qiskit IBM® Runtime بالكتلة المعلَّقة.
num_shots = 10_000
## Evaluate the problem using statevector-based primitives from Qiskit
# from qiskit.primitives import StatevectorSampler
# sampler = StatevectorSampler()
# results = sampler.run([overlap_circ]).result()
# counts = results[0].data.meas.get_int_counts()
# Evaluate the problem using a QPU via Qiskit IBM Runtime
sampler = Sampler(mode=backend)
results = sampler.run([overlap_ibm]).result()
counts = results[0].data.meas.get_int_counts()
visualize_counts(counts, num_qubits, num_shots)
الخطوة 4: المعالجة اللاحقة وإعادة النتيجة بالصيغة الكلاسيكية المطلوبة
- المدخل: توزيع الاحتمالات
- المخرج: عنصر واحد من مصفوفة النواة
احسب احتمال قياس |0> على دائرة التداخل، وأدرج قيمته في مصفوفة النواة في الموضع المقابل للعينتين اللتين تمثلهما هذه الدائرة (الصف 15، العمود 20). في هذا التمثيل البصري، يدل اللون الأحمر الداكن على قيم تشابه أقرب إلى 1.0. لملء مصفوفة النواة بأكملها، نحتاج إلى تشغيل تجربة كمية لكل عنصر.
# Calculate the fidelity, or the probability to measure 0
kernel_matrix[x1, x2] = counts.get(0, 0.0) / num_shots
print(f"Fidelity: {kernel_matrix[x1, x2]}")
Fidelity: 0.1279
نشر نمط Qiskit على السحابة
للقيام بذلك، انقل الكود المصدري أعلاه إلى ملف باسم ./source/generate_kernel_entry.py، ولف الكود في نص برمجي يأخذ مدخلات ويعيد الحل النهائي، ثم ارفعه إلى مجموعة بعيدة باستخدام الفئة QiskitFunction من Qiskit Serverless. للاطلاع على إرشادات حول تحديد التبعيات الخارجية وتمرير وسيطات الإدخال وما إلى ذلك، راجع أدلة Qiskit Serverless.
مدخل النمط هو زوج من عينات البيانات، x1 وx2. المخرج هو قيمة التشابه بين العينتين. ستُستخدم هذه القيمة لملء عنصر مصفوفة النواة المقابل لهاتين العينتين.
serverless = QiskitServerless()
kernel_entry_pattern = QiskitFunction(
title="generate-kernel-entry",
entrypoint="generate_kernel_entry.py",
working_dir="./source/",
)
serverless.upload(kernel_entry_pattern)
تشغيل نمط Qiskit كخدمة مُدارة
بعد رفع النمط إلى السحابة، يمكننا تشغيله بسهولة باستخدام عميل IBMServerlessProvider. للتبسيط، سنستخدم محاكياً كمياً دقيقاً في بيئة السحابة، وبذلك ستكون قيمة التشابه التي نحسبها دقيقة تمام اً.
generate_kernel_entry = serverless.load("generate-kernel-entry")
job = generate_kernel_entry.run(
sample1=list(X_train[x1]), sample2=list(X_train[x2])
)
kernel_matrix[x1, x2] = job.result()["fidelity"]
print(f"fidelity: {kernel_matrix[x1, x2]}")
استبيان البرنامج التعليمي
يُرجى ملء هذا الاستبيان القصير لتقديم ملاحظاتك حول هذا البرنام ج التعليمي. ستساعدنا آراؤك في تحسين محتوانا وتجربة المستخدم.