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

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

צעדים הבאים

המלצות