ข้ามไปยังเนื้อหาหลัก

Primitives ด้วย REST API (ส่วนที่ 1)

ขั้นตอนในหัวข้อนี้อธิบายวิธีรันและกำหนดค่า primitive workload ด้วย REST API และแสดงตัวอย่างการเรียกใช้งานในโปรแกรมใดก็ได้ที่ต้องการ

หมายเหตุ

เอกสารนี้ใช้ Python module requests เพื่อสาธิต Qiskit Runtime REST API อย่างไรก็ตาม workflow นี้สามารถรันโดยใช้ภาษาหรือ framework ใดก็ได้ที่รองรับการทำงานกับ REST API ดูรายละเอียดได้ใน เอกสาร API reference

Estimator primitive ด้วย REST API

1. เริ่มต้นบัญชี

เนื่องจาก Qiskit Runtime Estimator เป็นบริการแบบ managed จึงต้องเริ่มต้นบัญชีก่อน จากนั้นเลือกอุปกรณ์ที่ต้องการใช้คำนวณ expectation value

ดูรายละเอียดวิธีเริ่มต้นบัญชี ดู Backend ที่มี และยกเลิก token ได้ที่ หัวข้อนี้

2. สร้าง QASM circuit

ต้องมี circuit อย่างน้อยหนึ่งตัวเป็น input ให้ Estimator 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 ด้วย Estimator V2 API

หมายเหตุ

job ต่อไปนี้ใช้ Qiskit Runtime V2 primitives ทั้ง SamplerV2 และ EstimatorV2 รับ primitive unified bloc (PUB) หนึ่งตัวหรือมากกว่าเป็น input แต่ละ PUB คือ tuple ที่มี circuit หนึ่งตัวและข้อมูลที่ broadcast ไปยัง 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': '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 และดูผลลัพธ์

ส่ง 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-942fb30edcad
>>> Job Status: JobStatus.RUNNING

ดูผลลัพธ์ของ job:

response_result= requests.get(url+'/'+job_id+'/results', headers=headers)

res_dict=response_result.json()

estimator_result=res_dict['results']
print(estimator_result)

Output

[{'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 options

เทคนิค error mitigation ช่วยให้ผู้ใช้ลด error ใน circuit โดยสร้างแบบจำลอง noise ของอุปกรณ์ในขณะรัน โดยทั่วไปแล้วจะมี quantum pre-processing overhead ที่เกี่ยวข้องกับการฝึกโมเดล และ classical post-processing overhead เพื่อลด error ในผลลัพธ์ดิบโดยใช้โมเดลที่สร้างขึ้น

เทคนิค error mitigation ที่รวมอยู่ใน primitives คือตัวเลือก resilience ขั้นสูง ในการระบุตัวเลือกเหล่านี้ ให้ใช้ตัวเลือก resilience_level เมื่อส่ง job

ตัวอย่างต่อไปนี้สาธิตตัวเลือกเริ่มต้นสำหรับ 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 เป็นบริการแบบ managed จึงต้องเริ่มต้นบัญชีก่อน จากนั้นเลือกอุปกรณ์ที่ต้องการใช้รันการคำนวณ

ดูรายละเอียดวิธีเริ่มต้นบัญชี ดู Backend ที่มี และยกเลิก token ได้ที่ หัวข้อนี้

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 และ EstimatorV2 รับ primitive unified bloc (PUB) หนึ่งตัวหรือมากกว่าเป็น input แต่ละ PUB คือ tuple ที่มี circuit หนึ่งตัวและข้อมูลที่ broadcast ไปยัง 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 และดูผลลัพธ์

ส่ง 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. ทำงานกับ Runtime options

เทคนิค error mitigation ช่วยให้ผู้ใช้ลด error ใน circuit โดยสร้างแบบจำลอง noise ของอุปกรณ์ในขณะรัน โดยทั่วไปแล้วจะมี quantum pre-processing overhead ที่เกี่ยวข้องกับการฝึกโมเดล และ classical post-processing overhead เพื่อลด error ในผลลัพธ์ดิบโดยใช้โมเดลที่สร้างขึ้น

เทคนิค error mitigation ที่รวมอยู่ใน primitives คือตัวเลือก resilience ขั้นสูง ในการระบุตัวเลือกเหล่านี้ ให้ใช้ตัวเลือก resilience_level เมื่อส่ง job Sampler V2 ไม่รองรับการระบุ resilience level แต่สามารถเปิดหรือปิด error mitigation / suppression แต่ละวิธีได้

ตัวอย่างต่อไปนี้สาธิตตัวเลือกเริ่มต้นสำหรับ dynamical decoupling และ twirling ดูตัวเลือกเพิ่มเติมและรายละเอียดเพิ่มเติมได้ในหัวข้อ 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': '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 primitive ด้วย REST API และ parameterized circuits

1. เริ่มต้นบัญชี

เนื่องจาก Qiskit Runtime เป็นบริการแบบ managed จึงต้องเริ่มต้นบัญชีก่อน จากนั้นเลือกอุปกรณ์ที่ต้องการใช้รันการคำนวณ

ดูรายละเอียดวิธีเริ่มต้นบัญชี ดู Backend ที่มี และยกเลิก token ได้ที่ หัวข้อนี้

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. สร้าง quantum circuit และเพิ่ม gate แบบ parameterized

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

หมายเหตุ

job ต่อไปนี้ใช้ Qiskit Runtime V2 primitives ทั้ง SamplerV2 และ EstimatorV2 รับ primitive unified bloc (PUB) หนึ่งตัวหรือมากกว่าเป็น input แต่ละ PUB คือ tuple ที่มี circuit หนึ่งตัวและข้อมูลที่ broadcast ไปยัง 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": {
# 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')

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
  • อ่าน Migrate to V2 primitives
  • ฝึกกับ primitives ด้วยการเรียน Cost function lesson ใน IBM Quantum Learning
  • เรียนรู้วิธี transpile ในเครื่องในส่วน Transpile
  • Migrate to the Qiskit Runtime V2 primitives.
Source: IBM Quantum docs — updated 27 เม.ย. 2569
English version on doQumentation — updated 7 พ.ค. 2569
This translation based on the English version of 11 มี.ค. 2569