Estimator עם REST API
Package versions
הקוד בעמוד הזה פותח באמצעות הדרישות הבאות. אנחנו ממליצים להשתמש בגרסאות האלה או בגרסאות חדשות יותר.
qiskit[all]~=2.3.0
השלבים בנושא הזה מתארים איך להריץ ולהגדיר עומסי עבודה עם REST API, ומדגימים איך לקרוא להם מכל תוכנית שתרצה.
תיעוד זה משתמש במודול Python requests כדי להדגים את Qiskit Runtime REST API. עם זאת, תהליך העבודה הזה ניתן לביצוע בכל שפה או מסגרת שתומכת בעבודה עם REST APIs. ראה את תיעוד ה-API reference לפרטים נוספים.
1. אתחול החשבון
מכיוון ש-Qiskit Runtime Estimator הוא שירות מנוהל, קודם כל צריך לאתחל את החשבון שלך. אחר כך אפשר לבחור את המכשיר שבו תרצה להשתמש כדי לחשב את ערך הציפייה.
פרטים על איך לאתחל את החשבון, לצפות ב-Backend-ים זמינים ולבטל טוקנים אפשר למצוא בנושא הזה.
2. יצירת Circuit בפורמט QASM
נדרש לפחות Circuit אחד כקלט לפרימיטיב Estimator.
הגדר Circuit קוונטי בפורמט 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 עבר Transpiler למחרוזת חדשה resulting_qasm.
3. הרצת ה-Circuit הקוונטי באמצעות Estimator V2 API
המשימות הבאות משתמשות ב-Qiskit Runtime V2 primitives. גם SamplerV2 וגם EstimatorV2 מקבלים PUB אחד או יותר (primitive unified blocs) כקלט. כל PUB הוא tuple שמכיל Circuit אחד והנתונים המשודרים אליו, שיכולים לכלול מספר 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
טכניקות צמצום שגיאות מאפשרות למשתמשים לצמצם שגיאות Circuit על ידי מידול הרעש של המכשיר בזמן הביצוע. בדרך כלל הדבר גורם לתקורת עיבוד מוקדמת קוונטית הקשורה לאימון המודל, ולתקורת עיבוד מאוחרת קלאסית לצמצום שגיאות בתוצאות הגולמיות באמצעות המודל שנוצר.
טכניקות צמצום השגיאות המובנות בפרימיטיבים הן אפשרויות resilience מתקדמות. כדי לציין אפשרויות אלו, השתמש באפשרות resilience_level בעת שליחת המשימה.
הדוגמאות הבאות מדגימות את אפשרויות ברירת המחדל עבור dynamical decoupling, twirling ו-TREX + ZNE. מצא אפשרויות נוספות ופרטים נוספים בנושא Error mitigation and suppression techniques.
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}")
Circuit-ים פרמטריים
1. אתחול החשבון
מכיוון ש-Qiskit Runtime הוא שירות מנוהל, קודם כל צריך לאתחל את החשבון שלך. אחר כך אפשר לבחור את המכשיר שעליו תרצה להריץ את החישובים.
פרטים על איך לאתחל את החשבון, לצפות ב-Backend-ים זמינים ולבטל טוקנים אפשר למצוא בנושא הזה.
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. יצירת Circuit קוונטי והוספת Gates פרמטריים
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. הרצת ה-Circuit הקוונטי באמצעות 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, מצב session ומצב batch. למד איך לעבוד עם מצב session ומצב batch בנושא מצבי הביצוע. שים לב שמשתמשי Open Plan לא יכולים להגיש משימות session.
- למד איך לאתחל את החשבון שלך עם REST API.
- תרגל עם פרימיטיבים דרך שיעור פונקציית העלות ב-IBM Quantum® Learning.
- למד איך לבצע Transpiler מקומי בסעיף Transpile.