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

الـ Primitives مع REST API

تصف الخطوات في هذا الموضوع كيفية تشغيل وضبط أعباء عمل الـ primitive مع REST API، وتوضح كيفية استدعائها في أي برنامج تختاره.

ملاحظة

تستخدم هذه التوثيقات وحدة Python المسماة requests لإظهار Qiskit Runtime REST API. مع ذلك، يمكن تنفيذ هذا السير العملي بأي لغة أو إطار عمل يدعم التعامل مع REST APIs. راجع توثيق مرجع API للتفاصيل.

الـ Estimator primitive مع REST API

1. تهيئة الحساب

بما أن Qiskit Runtime Estimator خدمة مُدارة، فأنت بحاجة أولاً إلى تهيئة حسابك. يمكنك بعدها اختيار الجهاز الذي تريد استخدامه لحساب قيمة التوقع.

اعثر على تفاصيل كيفية تهيئة حسابك، وعرض الـ backends المتاحة، وإلغاء صلاحية الرموز في هذا الموضوع.

2. إنشاء دائرة QASM

تحتاج إلى دائرة واحدة على الأقل كمدخل لـ Estimator primitive.

عرّف دائرة كمية بصيغة QASM. مثلاً:

qasm_string='''
OPENQASM 3;
include "stdgates.inc";
qreg q[2];
creg c[2];
x q[0];
cx q[0], q[1];
c[0] = measure q[0];
c[1] = measure q[1];
'''

تفترض مقاطع الكود التالية أن qasm_string قد تم transpile إلى سلسلة جديدة تُسمى resulting_qasm.

3. تشغيل الدائرة الكمية باستخدام Estimator V2 API

ملاحظة

تستخدم المهام التالية Qiskit Runtime V2 primitives. كلٌّ من SamplerV2 و EstimatorV2 يأخذان مدخلاً واحداً أو أكثر من الـ primitive unified blocs (PUBs). كل PUB عبارة عن tuple يحتوي على دائرة واحدة والبيانات التي تُبثّ إليها، والتي يمكن أن تشمل observables ومعاملات متعددة. كل PUB يُعيد نتيجة.

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}

job_input = {
'program_id': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each.
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
}}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

4. التحقق من حالة المهمة والحصول على النتائج

بعد ذلك، مرّر job_id إلى الـ API:

response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')

المخرجات

>>> Job ID: 58223448-5100-4dec-a47a-942fb30edcad
>>> Job Status: JobStatus.RUNNING

احصل على نتائج المهمة:

response_result= requests.get(url+'/'+job_id+'/results', headers=headers)

res_dict=response_result.json()

estimator_result=res_dict['results']
print(estimator_result)

المخرجات

[{'data': {'evs': 0.7428980350102542, 'stds': 0.029884014518789213, 'ensemble_standard_error': 0.03261147170624149}, 'metadata': {'shots': 10016, 'target_precision': 0.01, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}}]

5. التعامل مع خيارات Runtime

تتيح تقنيات تخفيف الأخطاء للمستخدمين تقليل أخطاء الدائرة عن طريق نمذجة ضوضاء الجهاز وقت التنفيذ. يؤدي ذلك عادةً إلى تكلفة معالجة كمية مسبقة مرتبطة بتدريب النموذج، وتكلفة معالجة كلاسيكية لاحقة لتخفيف الأخطاء في النتائج الخام باستخدام النموذج المُولَّد.

تقنيات تخفيف الأخطاء المدمجة في الـ primitives هي خيارات resilience متقدمة. لتحديد هذه الخيارات، استخدم خيار resilience_level عند تقديم مهمتك.

توضح الأمثلة التالية الخيارات الافتراضية لـ dynamical decoupling وtwirling وTREX + ZNE. اعثر على المزيد من الخيارات والتفاصيل في موضوع تقنيات تخفيف الأخطاء وقمعها.

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "BACKEND_NAME"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"options": {
"resilience": {
"measure_mitigation": True,
"zne_mitigation": True,
"zne": {
"extrapolator":["exponential", "linear"],
"noise_factors":[1, 3, 5],
},
},
},
}
}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

الـ Sampler primitive مع REST API

1. تهيئة الحساب

بما أن Qiskit Runtime Sampler خدمةٌ مُدارة، تحتاج أولاً إلى تهيئة حسابك، ثم تختار الجهاز الذي تريد تشغيل حساباتك عليه.

ستجد تفاصيل حول كيفية تهيئة حسابك وعرض الـ backends المتاحة وإلغاء صلاحية الرموز المميزة في هذا الموضوع.

2. إنشاء دائرة QASM

تحتاج إلى دائرة واحدة على الأقل كمدخل للـ Sampler primitive.

عرِّف دائرة كمية بصيغة QASM:

qasm_string='''
OPENQASM 3;
include "stdgates.inc";
qreg q[2];
creg c[2];
x q[0];
cx q[0], q[1];
c[0] = measure q[0];
c[1] = measure q[1];
'''

تفترض مقتطفات الكود التالية أن qasm_string قد تم ترجمته إلى سلسلة نصية جديدة اسمها resulting_qasm.

3. تشغيل الدائرة الكمية باستخدام Sampler V2 API

ملاحظة

المهام التالية تستخدم الـ V2 primitives من Qiskit Runtime. كلٌّ من SamplerV2 وEstimatorV2 يقبلان مدخلاً واحداً أو أكثر من الوحدات الموحدة البدائية (PUBs). كل PUB عبارة عن مجموعة tuple تحتوي على دائرة واحدة والبيانات المُبثَّة إليها، والتي قد تشمل مراقبات ومعاملات متعددة. كل PUB يُعيد نتيجة.

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
"pubs": [[resulting_qasm],[resulting_qasm,None,500]] # primitive unified blocs (PUBs) containing one circuit each.
}}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

4. التحقق من حالة المهمة والحصول على النتائج

بعد ذلك، مرِّر job_id إلى الـ API:

response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')

المخرجات

>>> Job ID: 58223448-5100-4dec-a47a-942fb30edced
>>> Job Status: JobStatus.RUNNING

احصل على نتائج المهمة:

response_result= requests.get(url+'/'+job_id+'/results', headers=headers)

res_dict=response_result.json()

# Get results for the first PUB
counts=res_dict['results'][0]['data']['c']['samples']

print(counts[:20])

المخرجات

['0x3', '0x0', '0x2', '0x1', '0x0', '0x3', '0x0', '0x3', '0x1', '0x2', '0x2', '0x0', '0x2', '0x0', '0x3', '0x3', '0x2', '0x0', '0x1', '0x0']

5. العمل مع خيارات Runtime

تتيح تقنيات تخفيف الأخطاء للمستخدمين تقليل أخطاء الدائرة عن طريق نمذجة ضوضاء الجهاز وقت التنفيذ. يؤدي هذا عادةً إلى تكاليف معالجة مسبقة كمية مرتبطة بتدريب النموذج، وتكاليف معالجة لاحقة كلاسيكية لتخفيف الأخطاء في النتائج الخام باستخدام النموذج المُولَّد.

تقنيات تخفيف الأخطاء المدمجة في الـ primitives هي خيارات متانة متقدمة. لتحديد هذه الخيارات، استخدم الخيار resilience_level عند إرسال مهمتك. لا يدعم Sampler V2 تحديد مستويات المتانة. غير أنه يمكنك تفعيل أو تعطيل أساليب تخفيف الأخطاء أو قمعها بشكل فردي.

تُظهر الأمثلة التالية الخيارات الافتراضية للـ dynamical decoupling والـ twirling. ستجد المزيد من الخيارات والتفاصيل في موضوع تقنيات تخفيف الأخطاء وقمعها.

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
"pubs": [[resulting_qasm]], # primitive unified blocs (PUBs) containing one circuit each.
"options": {
"dynamical_decoupling": {
"enable": True,
"sequence_type": 'XpXm',
"extra_slack_distribution": 'middle',
"scheduling_method": 'alap',
},
},
}
}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

الـ Sampler primitive مع REST API والدوائر ذات المعاملات

1. تهيئة الحساب

بما أن Qiskit Runtime خدمةٌ مُدارة، تحتاج أولاً إلى تهيئة حسابك، ثم تختار الجهاز الذي تريد تشغيل حساباتك عليه.

ستجد تفاصيل حول كيفية تهيئة حسابك وعرض الـ backends المتاحة وإلغاء صلاحية الرموز المميزة في هذا الموضوع.

2. تعريف المعاملات

import requests
import qiskit_ibm_runtime
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.qasm3 import dumps
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit import transpile

service = QiskitRuntimeService(channel='ibm_quantum')
backend = service.backend("<SPECIFY BACKEND>")

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)

theta = Parameter('theta')
phi = Parameter('phi')
parameter_values = {'theta': 1.57, 'phi': 3.14} # In case we want to pass a dictionary

3. إنشاء دائرة كمية وإضافة بوابات ذات معاملات

qc = QuantumCircuit(2)

# Add parameterized gates
qc.rx(theta, 0)
qc.ry(phi, 1)
qc.cx(0, 1)
qc.measure_all()

# Draw the original circuit
qc.draw('mpl')

# Get an ISA circuit
isa_circuit = pm.run(qc)

4. توليد كود QASM 3

qasm_str = dumps(isa_circuit)
print("Generated QASM 3 code:")
print(qasm_str)

5. تشغيل الدائرة الكمية باستخدام Sampler V2 API

ملاحظة

المهام التالية تستخدم الـ primitives من Qiskit Runtime V2. كلٌّ من SamplerV2 وEstimatorV2 يقبلان مدخلاً واحداً أو أكثر من الوحدات الموحدة البدائية (PUBs). كل PUB عبارة عن مجموعة tuple تحتوي على دائرة واحدة والبيانات المُبثَّة إليها، والتي قد تشمل مراقبات ومعاملات متعددة. كل PUB يُعيد نتيجة.

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}

job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
# Choose one option: direct parameter transfer or through a dictionary
#"pubs": [[qasm_str,[1,2],500]], # primitive unified blocs (PUBs) containing one circuit each.
"pubs": [[qasm_str,parameter_values,500]], # primitive unified blocs (PUBs) containing one circuit each.
}}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print(f"Job created: {response.text}")
else:
print(f"Error: {response.status_code}")
print(response.text)

6. التحقق من حالة المهمة والحصول على النتائج

بعد ذلك، مرِّر job_id إلى الـ API:

response_status_singlejob = requests.get(f"{url}/{job_id}", headers=headers)
response_status_singlejob.json().get('state')

المخرجات

{'status': 'Completed'}

احصل على نتائج المهمة:

response_result = requests.get(f"{url}/{job_id}/results", headers=headers)

res_dict=response_result.json()

# Get results for the first PUB
counts=res_dict['results'][0]['data']['c']['samples']

print(counts[:20])

المخرجات

['0x1', '0x2', '0x1', '0x2', '0x1', '0x2', '0x0', '0x2', '0x1', '0x1', '0x2', '0x2', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1']

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

توصيات