Запусти свою першу схему на обладнанні
Package versions
Код на цій сторінці був розроблений з використанням наступних вимог. Ми рекомендуємо використовувати ці версії або новіші.
qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1
Цей приклад складається з двох частин. Спочатку ти створиш просту квантову програму "Hello world" та запустиш її на квантовому процесорі (QPU). Оскільки справжні квантові дослідження потребують набагато надійніших програм, у другому розділі (Масштабування до великої кількості кубітів) ти масштабуєш просту програму до рівня корисності.
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib qiskit qiskit-ibm-runtime
Встановлення та автентифікація
-
Якщо ти ще не встановив Qiskit, знайди інструкції в посібнику Швидкий старт.
-
Встанови Qiskit Runtime для виконання завдань на квантовому обладнанні:
pip install qiskit-ibm-runtime -
Налаштуй середовище для локального запуску Jupyter notebooks:
pip install jupyter
-
-
Налаштуй автентифікацію для доступу до квантового обладнання через безкоштовний Відкритий План.
(Якщо тобі надіслали запрошення приєднатися до облікового запису, натомість виконай кроки для запрошених користувачів.)
-
Перейди на IBM Quantum Platform, щоб увійти або створити обліковий запис.
ВажливоЯкщо ти підключаєшся через проксі-сервер, ти повинен використовувати Qiskit Runtime v0.44.0 або пізнішу версію.
-
Згенеруй свій API ключ (також званий API токеном) на панелі керування, потім скопіюй його в безпечне місце.
-
Перейди на сторінку Екземпляри і знайди екземпляр, який ти хочеш використовувати. Наведи курсор на його CRN і клацни, щоб скопіювати його.
-
Збережи свої облікові дані локально за допомогою цього коду:
from qiskit_ibm_runtime import QiskitRuntimeServiceQiskitRuntimeService.save_account(# For `token`, use the 44-character API_KEY you created# and saved from the IBM Quantum Platform Home dashboardtoken="<your-api-key>",instance="<CRN>", # Optional)
-
-
Тепер ти можеш використовувати цей код Python будь-коли, коли тобі потрібно автентифікуватися в Qiskit Runtime Service:
from qiskit_ibm_runtime import QiskitRuntimeService# Run every time you need the serviceservice = QiskitRuntimeService()
Якщо ти використовуєш публічний комп'ютер або інше незахищене середовище, натомість виконай інструкції ручної автентифікації, щоб зберегти твої облікові дані в безпеці.
Створення та запуск простої квантової програми
Чотири кроки для написання квантової програми з використанням шаблонів Qiskit:
-
Відобрази задачу у квантовий формат.
-
Оптимізуй схеми та оператори.
-
Виконай за допомогою функції квантового примітиву.
-
Проаналізуй результати.
Крок 1. Відображення задачі у квантовий формат
У квантовій програмі квантові схеми — це нативний формат для представлення квантових інструкцій, а оператори представляють спостережувані величини, які потрібно виміряти. Під час створення схеми ти зазвичай створюєш новий об'єкт QuantumCircuit, а потім послідовно додаєш до нього інструкції.
Наступна комірка коду створює схему, яка генерує стан Белла, який є станом, в якому два кубіти повністю заплутані один з одним.
Qiskit SDK використовує нумерацію бітів LSb 0, де -а цифра має значення або . Для отримання додаткової інформації дивись тему Порядок бітів у Qiskit SDK.
# This cell is hidden from users. It hides several unnecessary warnings.
import warnings
import logging
warnings.filterwarnings("ignore", message=".*Instance was not set*")
warnings.filterwarnings("ignore", message=".*loading instance*")
warnings.filterwarnings("ignore", message=".*using instance*")
# This cell is hidden from users. It hides several unnecessary warnings.
class IgnoreSpecificMessages(logging.Filter):
def filter(self, record):
for text in [
"Instance was not set",
"Loading default saved account",
"Loading instance",
"Instance was not set",
"using instance",
]:
if text in record.getMessage():
return False
return True
logger = logging.getLogger("qiskit_ibm_runtime")
logger.addFilter(IgnoreSpecificMessages())
for handler in logger.handlers:
handler.addFilter(IgnoreSpecificMessages())
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorOptions
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from matplotlib import pyplot as plt
# Uncomment the next line if you want to use a simulator:
# from qiskit_ibm_runtime.fake_provider import FakeBelemV2
# Create a new circuit with two qubits
qc = QuantumCircuit(2)
# Add a Hadamard gate to qubit 0
qc.h(0)
# Perform a controlled-X gate on qubit 1, controlled by qubit 0
qc.cx(0, 1)
# Return a drawing of the circuit using MatPlotLib ("mpl").
# These guides are written by using Jupyter notebooks, which
# display the output of the last line of each cell.
# If you're running this in a script, use `print(qc.draw())` to
# print a text drawing.
qc.draw("mpl")
Дивись QuantumCircuit у документації для всіх доступних операцій.
Під час створення квантових схем ти також повинен враховувати, який тип даних ти хочеш отримати після виконання. Qiskit надає два способи повернення даних: ти можеш отримати результати вибірки для набору кубітів, які ти вирішиш виміряти, або ти можеш отримати очікуване значення спостережуваної величини. Підготуй своє завдання для вимірювання твоєї схеми одним з цих двох способів за допомогою примітивів Qiskit (детально пояснюється в Кроці 3).
Цей приклад вимірює очікувані значення, використовуючи підмодуль qiskit.quantum_info, який визначається за допомогою операторів (математичних об'єктів, що використовуються для представлення дії або процесу, який змінює квантовий стан). Наступна комірка коду створює шість двокубітних операторів Паулі: IZ, IX, ZI, XI, ZZ та XX.
# Set up six different observables.
observables_labels = ["IZ", "IX", "ZI", "XI", "ZZ", "XX"]
observables = [SparsePauliOp(label) for label in observables_labels]
Тут щось на зразок оператора ZZ — це скорочення для тензорного добутку , що означає вимірювання Z на кубіті 1 та Z на кубіті 0 разом та отримання інформації про кореляцію між кубітом 1 і кубітом 0. Очікувані значення, подібні до цього, також зазвичай записуються як .
Якщо стан заплутаний, то вимірювання повинно відрізнятися від вимірювання . Для конкретного заплутаного стану, створеного нашою схемою, описаною вище, вимірювання повинно бути 1, а вимірювання повинно бути нуль.
Крок 2. Оптимізація схем та операторів
Під час виконання схем на пристрої важливо оптимізувати набір інструкцій, які містить схема, і мінімізувати загальну глибину (приблизно кількість інструкцій) схеми. Це забезпечує отримання найкращих можливих результатів шляхом зменшення впливу помилок та шуму. Крім того, інструкції схеми повинні відповідати архітектурі набору інструкцій (ISA) пристрою backend і повинні враховувати базові вентилі пристрою та зв'язність кубітів.
Наступний код створює екземпляр реального пристрою для подання завдання та перетворює схему та спостережувані величини відповідно до ISA цього backend. Це вимагає, щоб ти вже зберіг свої облікові дані
service = QiskitRuntimeService()
backend = service.least_busy(simulator=False, operational=True)
# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)
isa_circuit.draw("mpl", idle_wires=False)
Крок 3. Виконання за допомогою квантових примітивів
Квантові комп'ютери можуть виробляти випадкові результати, тому ти зазвичай збираєш вибірку виходів, запускаючи схему багато разів. Ти можеш оцінити значення спостережуваної величини, використовуючи клас Estimator. Estimator є одним з двох примітивів; інший — це Sampler, який можна використовувати для отримання даних з квантового комп'ютера. Ці об'єкти мають метод run(), який виконує вибір схем, спостережуваних величин та параметрів (якщо застосовно), використовуючи примітивний уніфікований блок (PUB).
# Construct the Estimator instance.
estimator = Estimator(mode=backend)
estimator.options.resilience_level = 1
estimator.options.default_shots = 5000
mapped_observables = [
observable.apply_layout(isa_circuit.layout) for observable in observables
]
# One pub, with one circuit to run against five different observables.
job = estimator.run([(isa_circuit, mapped_observables)])
# Use the job ID to retrieve your job data later
print(f">>> Job ID: {job.job_id()}")
>>> Job ID: d8286mfoha1c73bl8hrg
Після подання завдання ти можеш почекати, поки завдання буде завершено у твоєму поточному екземплярі python, або використовувати job_id для отримання даних пізніше. (Докладніше дивись розділ про отримання завдань.)
Після завершення завдання перевір його вивід через атрибут result() завдання.
# This is the result of the entire submission. You submitted one Pub,
# so this contains one inner result (and some metadata of its own).
job_result = job.result()
# This is the result from our single pub, which had six observables,
# so contains information on all six.
pub_result = job.result()[0]
# Check there are six observables.
# If not, edit the comments in the previous cell and update this test.
assert len(pub_result.data.evs) == 6
Коли ти запускаєш свою квантову програму на реальному пристрої, твоє завдання повинно чекати в черзі перед запуском. Щоб заощадити час, ти можеш натомість використовувати наступний код для запуску цього невеликого завдання на fake_provider з режимом локального тестування Qiskit Runtime. Зверни увагу, що це можливо лише для невеликої схеми. Коли ти масштабуватимеш у наступному розділі, тобі потрібно буде використовувати реальний пристрій.
# Use the following code instead if you want to run on a simulator:
from qiskit_ibm_runtime.fake_provider import FakeBelemV2
backend = FakeBelemV2()
estimator = Estimator(backend)
# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)
mapped_observables = [
observable.apply_layout(isa_circuit.layout) for observable in observables
]
job = estimator.run([(isa_circuit, mapped_observables)])
result = job.result()
# This is the result of the entire submission. You submitted one Pub,
# so this contains one inner result (and some metadata of its own).
job_result = job.result()
# This is the result from our single pub, which had five observables,
# so contains information on all five.
pub_result = job.result()[0]
Крок 4. Аналіз результатів
Крок аналізу зазвичай є місцем, де ти можеш постобробити свої результати, використовуючи, наприклад, пом'якшення помилок вимірювання або екстраполяцію нульового шуму (ZNE). Ти можеш передати ці результати в інший робочий процес для подальшого аналізу або підготувати графік ключових значень і даних. Загалом, цей крок є специфічним для твоєї задачі. Для цього прикладу побудуй графік кожного з очікуваних значень, які були виміряні для нашої схеми.
Очікувані значення та стандартні відхилення для спостережуваних величин, які ти вказав для Estimator, доступні через атрибути PubResult.data.evs та PubResult.data.stds результату завдання. Щоб отримати результати з Sampler, використовуй функцію PubResult.data.meas.get_counts(), яка поверне dict вимірювань у вигляді бітрядків як ключів та кількості як відповідних значень. Для отримання додаткової інформації дивись посібник Quickstart для Sampler.
# Plot the result
values = pub_result.data.evs
errors = pub_result.data.stds
# plotting graph
plt.plot(observables_labels, values, "-o")
plt.xlabel("Observables")
plt.ylabel("Values")
plt.show()
Зверни увагу, що для кубітів 0 та 1 незалежні очікувані значення як X, так і Z дорівнюють 0, тоді як кореляції (XX та ZZ) дорівнюють 1. Це ознака квантової заплутаності.
# Make sure the results follow the claim from the previous markdown cell.
# This can happen when the device occasionally behaves strangely. If this cell
# fails, you may just need to run the notebook again.
_results = {obs: val for obs, val in zip(observables_labels, values)}
for _label in ["IZ", "IX", "ZI", "XI"]:
assert abs(_results[_label]) < 0.2
for _label in ["XX", "ZZ"]:
assert _results[_label] > 0.8
Масштабування до великої кількості кубітів
У квантових обчисленнях робота на рівні корисності має вирішальне значення для досягнення прогресу в цій галузі. Така робота вимагає обчислень у набагато більшому масштабі; роботи зі схемами, які можуть використовувати понад 100 кубітів і понад 1000 вентилів. Цей приклад демонструє, як ти можеш виконувати роботу на рівні корисності на QPU IBM®, створюючи та аналізуючи 100-кубітний стан GHZ. Він використовує робочий процес шаблонів Qiskit і закінчується вимірюванням очікуваного значення для кожного кубіта.
Крок 1. Відображення задачі
Напиши функцію, яка повертає QuantumCircuit, що підготовлює -кубітний стан GHZ (по суті, розширений стан Белла), потім використовуй цю функцію для підготовки 100-кубітного стану GHZ і збери спостережувані величини для вимірювання.
def get_qc_for_n_qubit_GHZ_state(n: int) -> QuantumCircuit:
"""This function will create a qiskit.QuantumCircuit (qc)
for an n-qubit GHZ state.
Args:
n (int): Number of qubits in the n-qubit GHZ state
Returns:
QuantumCircuit: Quantum circuit that generate the n-qubit GHZ state,
assuming all qubits start in the 0 state
"""
if isinstance(n, int) and n >= 2:
qc = QuantumCircuit(n)
qc.h(0)
for i in range(n - 1):
qc.cx(i, i + 1)
else:
raise Exception("n is not a valid input")
return qc
# Create a new circuit with 100 qubits in the GHZ state
n = 100
qc = get_qc_for_n_qubit_GHZ_state(n)
Далі відобрази на оператори, які тебе цікавлять. Цей приклад використовує оператори ZZ між кубітами для вивчення поведінки в міру їх віддалення. Все більш неточні (пошкоджені) очікувані значення між віддаленими кубітами виявили б рівень присутнього шуму.
# ZZII...II, ZIZI...II, ... , ZIII...IZ
operator_strings = [
"Z" + "I" * i + "Z" + "I" * (n - 2 - i) for i in range(n - 1)
]
operators = [SparsePauliOp(operator) for operator in operator_strings]
Крок 2. Оптимізація задачі для виконання на квантовому обладнанні
Наступний код перетворює схему та спостережувані величини відповідно до ISA backend. Це вимагає, щоб ти вже зберіг свої облікові дані
service = QiskitRuntimeService()
backend = service.least_busy(
simulator=False, operational=True, min_num_qubits=100
)
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(qc)
isa_operators_list = [op.apply_layout(isa_circuit.layout) for op in operators]
Крок 3. Виконання на обладнанні
Подай завдання та увімкни придушення помилок, використовуючи техніку зменшення помилок під назвою динамічне роз'єднання. Рівень стійкості визначає, яку стійкість до помилок слід забезпечити. Вищі рівні генерують більш точні результати за рахунок більш тривалого часу обробки. Для подальшого пояснення опцій, встановлених у наступному коді, дивись Налаштування пом'якшення помилок для Qiskit Runtime.
options = EstimatorOptions()
options.resilience_level = 1
options.dynamical_decoupling.enable = True
options.dynamical_decoupling.sequence_type = "XY4"
# Create an Estimator object
estimator = Estimator(backend, options=options)
# Submit the circuit to Estimator
job = estimator.run([(isa_circuit, isa_operators_list)])
job_id = job.job_id()
print(job_id)
d828aeo0bvlc73d1vs20
Крок 4. Постобробка результатів
Після завершення завдання побудуй графік результатів і зверни увагу, що зменшується зі збільшенням , хоча в ідеальній симуляції всі повинні бути 1.
# data
data = list(range(1, len(operators) + 1)) # Distance between the Z operators
result = job.result()[0]
values = result.data.evs # Expectation value at each Z operator.
values = [
v / values[0] for v in values
] # Normalize the expectation values to evaluate how they decay with distance.
# plotting graph
plt.plot(data, values, marker="o", label="100-qubit GHZ state")
plt.xlabel("Distance between qubits $i$")
plt.ylabel(r"$\langle Z_i Z_0 \rangle / \langle Z_1 Z_0 \rangle $")
plt.legend()
plt.show()
Попередній графік показує, що в міру збільшення відстані між кубітами сигнал загасає через наявність шуму.
Наступні кроки
- Спробуй один з цих підручників:
- Оцінка енергії основного стану ланцюга Гейзенберга за допомогою VQE
- Вирішуй задачі оптимізації, використовуючи QAOA
- Навчай моделі квантових ядер для завдань машинного навчання
- Знайди детальні інструкції зі встановлення в посібнику Встановлення Qiskit.
- Якщо ти не бажаєш встановлювати Qiskit локально, прочитай про варіанти використання Qiskit в онлайн-середовищі розробки.
- Щоб зберегти кілька облікових даних або вказати інші параметри облікового запису, дивись детальні інструкції в посібнику Збереження облікових даних для входу.