Перейти до основного вмісту

Estimator з REST API

Версії пакетів

Код на цій сторінці було розроблено з використанням наступних вимог. Рекомендуємо використовувати ці або новіші версії.

qiskit[all]~=2.3.0

Кроки в цій темі описують, як запускати та налаштовувати робочі навантаження за допомогою REST API, і демонструють, як викликати їх у будь-якій програмі на твій вибір.

примітка

Ця документація використовує модуль Python requests для демонстрації Qiskit Runtime REST API. Однак цей робочий процес можна виконати будь-якою мовою або фреймворком, що підтримує роботу з REST API. Деталі дивись у довідковій документації API.

1. Ініціалізація акаунту

Оскільки Qiskit Runtime Estimator — це керований сервіс, спочатку потрібно ініціалізувати свій акаунт. Після цього ти зможеш обрати пристрій, який хочеш використовувати для обчислення очікуваного значення.

Деталі про те, як ініціалізувати акаунт, переглянути доступні бекенди та анулювати токени, читай у цій темі.

2. Створення QASM-схеми

Потрібна хоча б одна схема як вхідні дані для примітива Estimator.

Визнач квантову схему 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 було транспільовано в новий рядок resulting_qasm.

3. Запуск квантової схеми за допомогою API Estimator V2

примітка

Наступні завдання використовують примітиви Qiskit Runtime V2. І SamplerV2, і EstimatorV2 приймають один або кілька примітивних уніфікованих блоків (PUB) як вхідні дані. Кожен PUB — це кортеж, що містить одну схему і дані, які транслюються на цю схему (кілька спостережуваних і параметрів). Кожен 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

Техніки пом'якшення помилок дозволяють користувачам зменшувати помилки схем, моделюючи шум пристрою на момент виконання. Зазвичай це призводить до накладних витрат на квантову попередню обробку, пов'язаних із навчанням моделі, та класичних накладних витрат на подальшу обробку для зменшення помилок у сирих результатах за допомогою згенерованої моделі.

Техніки пом'якшення помилок, вбудовані в примітиви, є розширеними параметрами стійкості. Щоб задати ці параметри, використовуй опцію resilience_level під час відправки завдання.

Наступні приклади демонструють параметри за замовчуванням для динамічного розв'язання, твірлінгу та TREX + ZNE. Більше параметрів і детальну інформацію дивись у темі Техніки пом'якшення та придушення помилок.

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}")

Динамічне розв'язання

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}")

Твірлінг

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}")

Параметризовані схеми

1. Ініціалізація акаунту

Оскільки Qiskit Runtime — це керований сервіс, спочатку потрібно ініціалізувати свій акаунт. Після цього ти зможеш обрати пристрій, який хочеш використовувати для виконання своїх обчислень.

Деталі про те, як ініціалізувати акаунт, переглянути доступні бекенди та анулювати токени, читай у цій темі.

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. Створення квантової схеми та додавання параметризованих вентилів

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. Запуск квантової схеми за допомогою API Estimator V2

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

Наступні кроки

Рекомендації
  • Є кілька способів запускати робочі навантаження залежно від твоїх потреб: режим завдання, режим сесії та пакетний режим. Дізнайся, як працювати з режимом сесії та пакетним режимом, у темі режими виконання. Зауваж, що користувачі тарифу Open Plan не можуть надсилати завдання в режимі сесії.
  • Дізнайся, як ініціалізувати свій акаунт через REST API.
  • Практикуйся з примітивами, працюючи з уроком про функцію вартості в IBM Quantum® Learning.
  • Дізнайся, як виконувати транспіляцію локально, у розділі Транспіляція.