Sampler กับ REST API
ขั้นตอนในหัวข้อนี้อธิบายวิธีรันและกำหนดค่า workload ด้วย REST API พร้อมสาธิตวิธีเรียกใช้งานในโปรแกรมที่คุณเลือก
เอกสารนี้ใช้ Python module requests เพื่อสาธิต Qiskit Runtime REST API อย่างไรก็ตาม workflow นี้สามารถรันด้วยภาษาหรือ framework ใดก็ได้ที่รองรับการทำงานกับ REST API ดูรายละเอียดได้ที่ เอกสาร API reference
1. เริ่มต้นบัญชี
เนื่องจาก Qiskit Runtime Sampler เป็น managed service คุณต้องเริ่มต้นบัญชีก่อน จากนั้นจึงเลือกอุปกรณ์ที่ต้องการใช้รันการคำนวณ
ดูรายละเอียดวิธีเริ่มต้นบัญชี ดู Backend ที่ใช้งานได้ และจัดการ token ได้ที่ ตั้งค่าการใช้งาน IBM Quantum Platform ด้วย REST API
2. สร้าง QASM circuit
คุณต้องมี circuit อย่างน้อยหนึ่งตัวเป็น input ให้กับ Sampler primitive
กำหนด QASM quantum circuit:
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 แล้วเป็น string ใหม่ชื่อ resulting_qasm
3. รัน quantum circuit ด้วย Sampler V2 API
Job ด้านล่างใช้ Qiskit Runtime V2 primitives SamplerV2 รับ primitive unified bloc (PUB) หนึ่งตัวหรือมากกว่าเป็น input แต่ละ PUB คือ tuple ที่ประกอบด้วย circuit หนึ่งตัวและข้อมูลที่ broadcast ไปยัง circuit นั้น ซึ่งอาจมีหลาย parameter และให้ผลลัพธ์หนึ่งค่าต่อ 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 และดูผลลัพธ์
ต่อไป ส่ง job_id ไปยัง API:
response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')
Output
>>> Job ID: 58223448-5100-4dec-a47a-942fb30edced
>>> Job Status: JobStatus.RUNNING
ดูผลลัพธ์ job:
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])
Output
['0x3', '0x0', '0x2', '0x1', '0x0', '0x3', '0x0', '0x3', '0x1', '0x2', '0x2', '0x0', '0x2', '0x0', '0x3', '0x3', '0x2', '0x0', '0x1', '0x0']
5. ทำงานกับ Qiskit Runtime options
เทคนิคการลด error ช่วยให้ผู้ใช้บรรเทา error ของ circuit โดยจำลอง noise ของอุปกรณ์ในช่วงเวลาที่รัน ซึ่งโดยทั่วไปส่งผลให้มี overhead ในการประมวลผลเชิงควอนตัมก่อนรัน (เกี่ยวกับการเทรนโมเดล) และ overhead ในการประมวลผลแบบคลาสสิกหลังรัน เพื่อลด error ในผลลัพธ์ดิบโดยใช้โมเดลที่สร้างขึ้น
เทคนิคการลด error ที่ฝังอยู่ใน primitives คือ resilience options ขั้นสูง ในการระบุ options เหล่านี้ ให้ใช้ option resilience_level เมื่อส่ง job
Sampler V2 ไม่รองรับการระบุ resilience level แต่คุณสามารถเปิดหรือปิดเทคนิคการลด/ลดทอน error แต่ละแบบได้
ตัวอย่างต่อไปนี้แสดง option เริ่มต้นสำหรับ dynamical decoupling และ twirling ดู option เพิ่มเติมและรายละเอียดได้ที่หัวข้อ เทคนิคการลด error และการลดทอน error
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}")
Circuit แบบมี parameter
1. เริ่มต้นบัญชี
เนื่องจาก Qiskit Runtime เป็น managed service คุณต้องเริ่มต้นบัญชีก่อน จากนั้นจึงเลือกอุปกรณ์ที่ต้องการใช้รันการคำนวณ
ดูรายละเอียดวิธีเริ่มต้นบัญชี ดู Backend ที่ใช้งานได้ และยกเลิก token ได้ที่หัวข้อนี้
2. กำหนด parameter
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. สร้าง quantum circuit และเพิ่ม Gate แบบมี parameter
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. รัน quantum circuit ด้วย 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 และดูผลลัพธ์
ต่อไป ส่ง job_id ไปยัง API:
response_status_singlejob = requests.get(f"{url}/{job_id}", headers=headers)
response_status_singlejob.json().get('state')
Output
{'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])
Output
['0x1', '0x2', '0x1', '0x2', '0x1', '0x2', '0x0', '0x2', '0x1', '0x1', '0x2', '0x2', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1']
ขั้นตอนถัดไป
- มีหลายวิธีในการรัน workload ขึ้นอยู่กับความต้องการ: job mode, session mode และ batch mode เรียนรู้วิธีทำงานกับ session mode และ batch mode ได้ที่หัวข้อ execution modes โปรดทราบว่าผู้ใช้แผน Open Plan ไม่สามารถส่ง session job ได้
- เรียนรู้วิธีเริ่มต้นบัญชีด้วย REST API
- ฝึกใช้ primitives ผ่านบทเรียน Cost function ใน IBM Quantum Learning
- เรียนรู้วิธี transpile ในเครื่องได้ในส่วน Transpile