Sampler עם REST API
השלבים בנושא זה מסבירים כיצד להריץ ולהגדיר עומסי עבודה עם REST API, ומדגימים כיצד להפעיל אותם בכל תוכנית שתבחר.
תיעוד זה משתמש במודול requests של Python כדי להדגים את Qiskit Runtime REST API. עם זאת, תהליך עבודה זה ניתן לביצוע באמצעות כל שפה או מסגרת שתומכת בעבודה עם REST APIs. עיין בתיעוד הפניית API לפרטים.
1. אתחול החשבון
מכיוון ש-Qiskit Runtime Sampler הוא שירות מנוהל, קודם צריך לאתחל את החשבון שלך. לאחר מכן אפשר לבחור את המכשיר שרוצים להשתמש בו להרצת החישובים.
מצא פרטים על כיצד לאתחל את החשבון שלך, לצפות ב-backends הזמינים ולעבוד עם tokens בהגדרת שימוש ב-IBM Quantum Platform עם REST API.
2. יצירת מעגל QASM
צריך לפחות Circuit אחד כקלט ל-primitive של Sampler.
הגדר מעגל קוונטי 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. הרצת המעגל הקוונטי באמצעות Sampler V2 API
העבודות להלן משתמשות ב-V2 primitives של Qiskit Runtime. SamplerV2 מקבל PUB (primitive unified bloc) אחד או יותר כקלט. כל 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": {
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[resulting_qasm],[resulting_qasm,None,500]]
}}
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. עבודה עם אפשרויות Qiskit Runtime
טכניקות הפחתת שגיאות מאפשרות למשתמשים להפחית שגיאות מעגל על ידי מידול רעש המכשיר בזמן ההרצה. זה בדרך כלל מביא לתקורת עיבוד מקדים קוונטי הקשורה לאימון מודל, ותקורת עיבוד לאחר קלאסית להפחתת שגיאות בתוצאות הגולמיות באמצעות המודל שנוצר.
טכניקות הפחתת השגיאות המובנות ב-primitives הן אפשרויות חוסן מתקדמות. כדי לציין אפשרויות אלה, השתמש באפשרות ה-resilience_level בעת שליחת העבודה.
Sampler V2 אינו תומך בציון רמות חוסן. עם זאת, ניתן להפעיל או לכבות שיטות הפחתת/דיכוי שגיאות בודדות.
הדוגמאות הבאות מדגימות את האפשרויות ברירת המחדל עבור dynamical decoupling ו-twirling. מצא אפשרויות נוספות ופרטים נוספים בנושא טכניקות הפחתת שגיאות ודיכוי שגיאות.
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': 'sampler',
"backend": backend,
"params": {
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[resulting_qasm]],
"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': 'sampler',
"backend": backend,
"params": {
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[resulting_qasm]],
"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 הזמינים ולבטל tokens בנושא זה.
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')
# In case we want to pass a dictionary:
parameter_values = {'theta': 1.57, 'phi': 3.14}
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
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
# # primitive unified blocs (PUBs) containing one circuit each:
#"pubs": [[qasm_str,[1,2],500]],
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[qasm_str,parameter_values,500]],
}}
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.
- תרגל עם primitives באמצעות עבודה על שיעור פונקציית עלות בלימוד IBM Quantum.
- למד כיצד לבצע transpile מקומית בחלק Transpile.