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

الـ Estimator مع REST API

Package versions

طُوِّر الكود الموجود في هذه الصفحة باستخدام المتطلبات التالية. نوصي باستخدام هذه الإصدارات أو أحدث منها.

qiskit[all]~=2.3.0

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

ملاحظة

تستخدم هذه التوثيقات وحدة Python المسماة requests لإظهار Qiskit Runtime REST API. مع ذلك، يمكن تنفيذ هذا السير العملي بأي لغة أو إطار عمل يدعم التعامل مع REST APIs. راجع توثيق مرجع 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. اعثر على المزيد من الخيارات والتفاصيل في موضوع تقنيات تخفيف الأخطاء وقمعها.

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}")

Dynamical Decoupling

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": {
"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}")

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': '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": {
"twirling": {
"enable_gates": True,
"enable_measure": True,
"num_randomizations": "auto",
"shots_per_randomization": "auto",
"strategy": "active-accum",
},
},
}
}

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}")

الدوائر ذات المعاملات

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. تشغيل الدائرة الكمية باستخدام Estimator V2 API

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": {
# 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']

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

توصيات
  • ثمة عدة طرق لتشغيل أعباء العمل، تبعاً لاحتياجاتك: وضع المهمة (job mode)، ووضع الجلسة (session mode)، ووضع الدُّفعة (batch mode). تعرَّف على كيفية العمل مع وضع الجلسة ووضع الدُّفعة في موضوع أوضاع التنفيذ. لاحظ أن مستخدمي الخطة المجانية (Open Plan) لا يستطيعون إرسال مهام الجلسة.
  • تعلَّم كيفية تهيئة حسابك مع REST API.
  • تدرَّب على الـ primitives من خلال درس دالة التكلفة في IBM Quantum® Learning.
  • تعلَّم كيفية الترجمة محلياً في قسم الترجمة (Transpile).