דלג לתוכן הראשי

פרימיטיבים עם REST API

השלבים בנושא זה מתארים איך להריץ ולהגדיר עומסי עבודה של פרימיטיבים עם REST API, ומדגימים איך לקרוא להם מכל תוכנית שתרצה.

הערה

תיעוד זה משתמש במודול Python ‏requests כדי להדגים את Qiskit Runtime REST API. עם זאת, תהליך עבודה זה ניתן לביצוע בכל שפה או מסגרת שתומכת בעבודה עם REST APIs. ראה את תיעוד ה-API reference לפרטים נוספים.

פרימיטיב Estimator עם REST API

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.

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 הוא שירות מנוהל, קודם כול צריך לאתחל את החשבון שלך. אחרי זה אפשר לבחור את המכשיר שעליו תרצה להריץ את החישובים.

פרטים על אתחול החשבון, צפייה ב-Backend-ים זמינים וביטול טוקנים נמצאים בנושא הזה.

2. יצירת Circuit בפורמט QASM

נדרש לפחות Circuit אחד כקלט ל-Sampler primitive.

הגדר 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 עבר transpilation למחרוזת חדשה resulting_qasm.

3. הרצת ה-Circuit הקוונטי באמצעות Sampler V2 API

הערה

העבודות הבאות משתמשות ב-Qiskit Runtime V2 primitives. גם SamplerV2 וגם EstimatorV2 מקבלים PUB אחד או יותר (primitive unified blocs) כקלט. כל PUB הוא tuple שמכיל Circuit אחד והנתונים המשודרים אליו, שיכולים להיות observable-ים ופרמטרים מרובים. כל 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

טכניקות הפחתת שגיאות מאפשרות למשתמשים להפחית שגיאות ב-Circuit על ידי מידול רעש המכשיר בזמן הביצוע. הדבר בדרך כלל מוביל לעלות עיבוד מוקדמת (pre-processing) הקשורה לאימון המודל, ועלות עיבוד קלאסי (post-processing) להפחתת שגיאות בתוצאות הגולמיות באמצעות המודל שנוצר.

טכניקות הפחתת השגיאות המובנות ב-primitives הן אפשרויות resilience מתקדמות. כדי לציין אפשרויות אלה, השתמש באפשרות resilience_level בעת שליחת העבודה. Sampler V2 אינו תומך בציון רמות resilience. עם זאת, ניתן להפעיל או לכבות שיטות הפחתה/דיכוי שגיאות בנפרד.

הדוגמאות הבאות מציגות את ברירות המחדל עבור 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 עם 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. יצירת 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 הקוונטי באמצעות Sampler V2 API

הערה

משימות ה-Job הבאות משתמשות ב-פרימיטיבים של Qiskit Runtime V2. גם 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': '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 וקבלת תוצאות

עכשיו צריך להעביר את ה-job_id ל-API:

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

פלט

{'status': 'Completed'}

קבלת תוצאות ה-Job:

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']

צעדים הבאים

המלצות