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

Ефективна симуляція стабілізаторних схем за допомогою примітивів Qiskit Aer

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

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

qiskit[all]~=2.3.0
qiskit-aer~=0.17

На цій сторінці показано, як використовувати примітиви Qiskit Aer для ефективної симуляції стабілізаторних схем, зокрема тих, що піддаються впливу шуму Паулі.

Стабілізаторні схеми, також відомі як схеми Кліффорда, є важливим обмеженим класом квантових схем, які можна ефективно симулювати класично. Існує кілька еквівалентних способів визначення стабілізаторних схем. Згідно з одним із них, стабілізаторна схема — це квантова схема, що складається виключно з таких вентилів:

Зауважимо, що за допомогою вентилів Адамара та S ми можемо побудувати будь-який вентиль повороту Паулі (RxR_x, RyR_y та RzR_z) з кутом із множини {0,π2,π,3π2}\{0, \frac{\pi}{2}, \pi, \frac{3\pi}{2}\} (з точністю до глобальної фази), тож ці вентилі також можна включати до визначення.

Стабілізаторні схеми є важливими для вивчення квантового виправлення помилок. Їхня класична симульованість також робить їх корисними для перевірки вихідних даних квантових комп'ютерів. Наприклад, уявімо, що ти хочеш виконати квантову схему на 100 кубітах на квантовому комп'ютері. Як переконатися, що квантовий комп'ютер поводиться правильно? Квантова схема на 100 кубітах перевищує можливості прямої класичної симуляції. Модифікуючи свою схему так, щоб вона стала стабілізаторною, ти можеш запускати схеми на квантовому комп'ютері, що мають структуру, подібну до бажаної, але які можна симулювати на класичному комп'ютері. Перевіряючи вивід квантового комп'ютера на стабілізаторних схемах, ти можеш переконатися в його правильній роботі і на нестабілізаторних схемах. Приклад цього підходу на практиці дивись у статті Evidence for the utility of quantum computing before fault tolerance.

У статті Точна та зашумлена симуляція за допомогою примітивів Qiskit Aer показано, як використовувати Qiskit Aer для точної та зашумленої симуляції загальних квантових схем. Розглянемо схему-приклад із тієї статті — схему на 8 кубітах, побудовану за допомогою efficient_su2:

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer
from qiskit.circuit.library import efficient_su2

n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")

Вивід попередньої комірки коду

Використовуючи Qiskit Aer, ми легко симулювали цю схему. Але уяви, що ми збільшуємо кількість кубітів до 500:

n_qubits = 500
circuit = efficient_su2(n_qubits)
# don't try to draw the circuit because it's too large

Оскільки вартість симуляції квантових схем зростає експоненційно з кількістю кубітів, така велика схема загалом перевищила б можливості навіть високопродуктивного симулятора, як-от Qiskit Aer. Класична симуляція загальних квантових схем стає нездійсненною, коли кількість кубітів перевищує приблизно від 50 до 100. Проте варто зауважити, що схема efficient_su2 параметризована кутами на вентилях RyR_y та RzR_z. Якщо всі ці кути належать множині {0,π2,π,3π2}\{0, \frac{\pi}{2}, \pi, \frac{3\pi}{2}\}, то схема є стабілізаторною та може бути ефективно симульована!

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

import numpy as np
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import SamplerV2 as Sampler

measured_circuit = circuit.copy()
measured_circuit.measure_all()

rng = np.random.default_rng(1234)
params = rng.choice(
[0, np.pi / 2, np.pi, 3 * np.pi / 2],
size=circuit.num_parameters,
)

# Initialize a Sampler backed by the stabilizer circuit simulator
exact_sampler = Sampler(
options=dict(backend_options=dict(method="stabilizer"))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(
1, AerSimulator(method="stabilizer")
)
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params)
job = exact_sampler.run([pub])
result = job.result()
pub_result = result[0]
counts = pub_result.data.meas.get_counts()

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

Наступна комірка коду виконує ту саму симуляцію, що й попередня, але цього разу задається модель шуму, що додає деполяризаційну помилку 2% до кожного вентиля CX, а також помилку зчитування, що перевертає кожен виміряний біт із ймовірністю 5%.

from qiskit_aer.noise import NoiseModel, depolarizing_error, ReadoutError

noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
bit_flip_prob = 0.05
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)
noise_model.add_all_qubit_readout_error(
ReadoutError(
[
[1 - bit_flip_prob, bit_flip_prob],
[bit_flip_prob, 1 - bit_flip_prob],
]
)
)

noisy_sampler = Sampler(
options=dict(
backend_options=dict(method="stabilizer", noise_model=noise_model)
)
)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
counts = pub_result.data.meas.get_counts()

Тепер скористаємося примітивом Estimator, підкріпленим симулятором стабілізаторних схем, для обчислення очікуваного значення спостережуваної ZZZZZ \cdots Z. Завдяки особливій структурі стабілізаторних схем результат, швидше за все, дорівнюватиме 0.

from qiskit.quantum_info import SparsePauliOp
from qiskit_aer.primitives import EstimatorV2 as Estimator

observable = SparsePauliOp("Z" * n_qubits)

exact_estimator = Estimator(
options=dict(backend_options=dict(method="stabilizer")),
)
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value
0.0

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

Рекомендації